[IMP] fields: reduce memory footprint of `field._attrs` and `column._args`
The optimization consists in sharing the dictionary when it is empty, which is the common case. This saves around 1.5Mb per registry.
This commit is contained in:
parent
4d232969a3
commit
3df7754087
|
@ -30,12 +30,13 @@ import logging
|
||||||
import pytz
|
import pytz
|
||||||
import xmlrpclib
|
import xmlrpclib
|
||||||
|
|
||||||
from openerp.tools import float_round, ustr, html_sanitize
|
from openerp.tools import float_round, frozendict, html_sanitize, ustr
|
||||||
from openerp.tools import DEFAULT_SERVER_DATE_FORMAT as DATE_FORMAT
|
from openerp.tools import DEFAULT_SERVER_DATE_FORMAT as DATE_FORMAT
|
||||||
from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT as DATETIME_FORMAT
|
from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT as DATETIME_FORMAT
|
||||||
|
|
||||||
DATE_LENGTH = len(date.today().strftime(DATE_FORMAT))
|
DATE_LENGTH = len(date.today().strftime(DATE_FORMAT))
|
||||||
DATETIME_LENGTH = len(datetime.now().strftime(DATETIME_FORMAT))
|
DATETIME_LENGTH = len(datetime.now().strftime(DATETIME_FORMAT))
|
||||||
|
EMPTY_DICT = frozendict()
|
||||||
|
|
||||||
_logger = logging.getLogger(__name__)
|
_logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -295,7 +296,8 @@ class Field(object):
|
||||||
|
|
||||||
def __init__(self, string=None, **kwargs):
|
def __init__(self, string=None, **kwargs):
|
||||||
kwargs['string'] = string
|
kwargs['string'] = string
|
||||||
self._attrs = {key: val for key, val in kwargs.iteritems() if val is not None}
|
attrs = {key: val for key, val in kwargs.iteritems() if val is not None}
|
||||||
|
self._attrs = attrs or EMPTY_DICT
|
||||||
|
|
||||||
# self._triggers is a set of pairs (field, path) that represents the
|
# self._triggers is a set of pairs (field, path) that represents the
|
||||||
# computed fields that depend on `self`. When `self` is modified, it
|
# computed fields that depend on `self`. When `self` is modified, it
|
||||||
|
@ -304,6 +306,15 @@ class Field(object):
|
||||||
self._triggers = set()
|
self._triggers = set()
|
||||||
self.inverse_fields = []
|
self.inverse_fields = []
|
||||||
|
|
||||||
|
def _set_attr(self, name, value):
|
||||||
|
""" Set the given field attribute, and add it to `_attrs` if necessary. """
|
||||||
|
object.__setattr__(self, name, value)
|
||||||
|
if not hasattr(type(self), name):
|
||||||
|
if self._attrs:
|
||||||
|
self._attrs[name] = value
|
||||||
|
else:
|
||||||
|
self._attrs = {name: value} # replace EMPTY_DICT
|
||||||
|
|
||||||
def new(self, **kwargs):
|
def new(self, **kwargs):
|
||||||
""" Return a field of the same type as `self`, with its own parameters. """
|
""" Return a field of the same type as `self`, with its own parameters. """
|
||||||
return type(self)(**kwargs)
|
return type(self)(**kwargs)
|
||||||
|
@ -337,11 +348,9 @@ class Field(object):
|
||||||
if not isinstance(attrs.get('column'), (NoneType, fields.function)):
|
if not isinstance(attrs.get('column'), (NoneType, fields.function)):
|
||||||
attrs.pop('store', None)
|
attrs.pop('store', None)
|
||||||
|
|
||||||
self._attrs = {}
|
self._attrs = EMPTY_DICT
|
||||||
for attr, value in attrs.iteritems():
|
for attr, value in attrs.iteritems():
|
||||||
if not hasattr(self, attr):
|
self._set_attr(attr, value)
|
||||||
self._attrs[attr] = value
|
|
||||||
setattr(self, attr, value)
|
|
||||||
|
|
||||||
if not self.string and not self.related:
|
if not self.string and not self.related:
|
||||||
# related fields get their string from their parent field
|
# related fields get their string from their parent field
|
||||||
|
@ -481,8 +490,7 @@ class Field(object):
|
||||||
|
|
||||||
for attr, value in field._attrs.iteritems():
|
for attr, value in field._attrs.iteritems():
|
||||||
if attr not in self._attrs:
|
if attr not in self._attrs:
|
||||||
self._attrs[attr] = value
|
self._set_attr(attr, value)
|
||||||
setattr(self, attr, value)
|
|
||||||
|
|
||||||
# special case for states: copy it only for inherited fields
|
# special case for states: copy it only for inherited fields
|
||||||
if not self.states and self.inherited:
|
if not self.states and self.inherited:
|
||||||
|
|
|
@ -48,11 +48,12 @@ from psycopg2 import Binary
|
||||||
import openerp
|
import openerp
|
||||||
import openerp.tools as tools
|
import openerp.tools as tools
|
||||||
from openerp.tools.translate import _
|
from openerp.tools.translate import _
|
||||||
from openerp.tools import float_round, float_repr
|
from openerp.tools import float_repr, float_round, frozendict, html_sanitize
|
||||||
from openerp.tools import html_sanitize
|
|
||||||
import simplejson
|
import simplejson
|
||||||
from openerp import SUPERUSER_ID, registry
|
from openerp import SUPERUSER_ID, registry
|
||||||
|
|
||||||
|
EMPTY_DICT = frozendict()
|
||||||
|
|
||||||
_logger = logging.getLogger(__name__)
|
_logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
def _symbol_set(symb):
|
def _symbol_set(symb):
|
||||||
|
@ -136,7 +137,7 @@ class _column(object):
|
||||||
if val:
|
if val:
|
||||||
setattr(self, key, val)
|
setattr(self, key, val)
|
||||||
|
|
||||||
self._args = args
|
self._args = args or EMPTY_DICT
|
||||||
for key, val in args.iteritems():
|
for key, val in args.iteritems():
|
||||||
setattr(self, key, val)
|
setattr(self, key, val)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue