[IMP] models: speedup loading of registry (-20%)
Idea: look up for the model's fields in method `_setup_base()` instead of method `__init__()`. This does not make a significant difference when installing or upgrading modules, but when simply loading a registry, the (expensive) field lookup is done once per model instead of once per class.
This commit is contained in:
parent
0167acbb52
commit
45a37b22fd
|
@ -297,6 +297,13 @@ class Field(object):
|
|||
self._attrs = {key: val for key, val in kwargs.iteritems() if val is not None}
|
||||
self._free_attrs = []
|
||||
|
||||
# self._triggers is a set of pairs (field, path) that represents the
|
||||
# computed fields that depend on `self`. When `self` is modified, it
|
||||
# invalidates the cache of each `field`, and registers the records to
|
||||
# recompute based on `path`. See method `modified` below for details.
|
||||
self._triggers = set()
|
||||
self.inverse_fields = []
|
||||
|
||||
def new(self, **kwargs):
|
||||
""" Return a field of the same type as `self`, with its own parameters. """
|
||||
return type(self)(**kwargs)
|
||||
|
@ -396,16 +403,6 @@ class Field(object):
|
|||
# Field setup
|
||||
#
|
||||
|
||||
def reset(self):
|
||||
""" Prepare `self` for a new setup. """
|
||||
self.setup_done = False
|
||||
# self._triggers is a set of pairs (field, path) that represents the
|
||||
# computed fields that depend on `self`. When `self` is modified, it
|
||||
# invalidates the cache of each `field`, and registers the records to
|
||||
# recompute based on `path`. See method `modified` below for details.
|
||||
self._triggers = set()
|
||||
self.inverse_fields = []
|
||||
|
||||
def setup(self, env):
|
||||
""" Make sure that `self` is set up, except for recomputation triggers. """
|
||||
if not self.setup_done:
|
||||
|
|
|
@ -636,8 +636,8 @@ class BaseModel(object):
|
|||
attrs = {
|
||||
'_name': name,
|
||||
'_register': False,
|
||||
'_columns': {}, # filled by _setup_fields()
|
||||
'_defaults': {}, # filled by Field._determine_default()
|
||||
'_columns': None, # recomputed in _setup_fields()
|
||||
'_defaults': None, # recomputed in _setup_base()
|
||||
'_inherits': dict(cls._inherits),
|
||||
'_depends': dict(cls._depends),
|
||||
'_constraints': list(cls._constraints),
|
||||
|
@ -750,9 +750,13 @@ class BaseModel(object):
|
|||
cls._onchange_methods = defaultdict(list)
|
||||
for attr, func in getmembers(cls, callable):
|
||||
if hasattr(func, '_constrains'):
|
||||
if not all(name in cls._fields for name in func._constrains):
|
||||
_logger.warning("@constrains%r parameters must be field names", func._constrains)
|
||||
cls._constraint_methods.append(func)
|
||||
if hasattr(func, '_onchange'):
|
||||
for name in func._onchange:
|
||||
if name not in cls._fields:
|
||||
_logger.warning("@onchange%r parameters must be field names", func._onchange)
|
||||
cls._onchange_methods[name].append(func)
|
||||
|
||||
def __new__(cls):
|
||||
|
@ -800,19 +804,6 @@ class BaseModel(object):
|
|||
"TransientModels must have log_access turned on, " \
|
||||
"in order to implement their access rights policy"
|
||||
|
||||
# retrieve new-style fields (from above registry class) and duplicate
|
||||
# them (to avoid clashes with inheritance between different models)
|
||||
cls._fields = {}
|
||||
above = cls.__bases__[0]
|
||||
for attr, field in getmembers(above, Field.__instancecheck__):
|
||||
cls._add_field(attr, field.new())
|
||||
|
||||
# introduce magic fields
|
||||
cls._add_magic_fields()
|
||||
|
||||
# register constraints and onchange methods
|
||||
cls._init_constraints_onchanges()
|
||||
|
||||
# prepare ormcache, which must be shared by all instances of the model
|
||||
cls._ormcache = {}
|
||||
|
||||
|
@ -2941,26 +2932,28 @@ class BaseModel(object):
|
|||
if cls._setup_done:
|
||||
return
|
||||
|
||||
# first make sure that parent models determine all their fields
|
||||
# 1. determine the proper fields of the model; duplicate them on cls to
|
||||
# avoid clashes with inheritance between different models
|
||||
for name in getattr(cls, '_fields', {}):
|
||||
delattr(cls, name)
|
||||
|
||||
# retrieve fields from parent classes
|
||||
cls._fields = {}
|
||||
cls._defaults = {}
|
||||
for attr, field in getmembers(cls, Field.__instancecheck__):
|
||||
cls._add_field(attr, field.new())
|
||||
|
||||
# add magic and custom fields
|
||||
cls._add_magic_fields()
|
||||
cls._init_manual_fields(self._cr, partial)
|
||||
|
||||
# 2. make sure that parent models determine their own fields, then add
|
||||
# inherited fields to cls
|
||||
cls._inherits_check()
|
||||
for parent in cls._inherits:
|
||||
self.env[parent]._setup_base(partial)
|
||||
|
||||
# remove inherited fields from cls._fields
|
||||
for name, field in cls._fields.items():
|
||||
if field.inherited:
|
||||
del cls._fields[name]
|
||||
|
||||
# retrieve custom fields
|
||||
cls._init_manual_fields(self._cr, partial)
|
||||
|
||||
# retrieve inherited fields
|
||||
cls._init_inherited_fields()
|
||||
|
||||
# prepare the setup of fields
|
||||
for field in cls._fields.itervalues():
|
||||
field.reset()
|
||||
|
||||
cls._setup_done = True
|
||||
|
||||
@api.model
|
||||
|
@ -2968,7 +2961,8 @@ class BaseModel(object):
|
|||
""" Setup the fields, except for recomputation triggers. """
|
||||
cls = type(self)
|
||||
|
||||
# set up fields, and update their corresponding columns
|
||||
# set up fields, and determine their corresponding column
|
||||
cls._columns = {}
|
||||
for name, field in cls._fields.iteritems():
|
||||
field.setup(self.env)
|
||||
if field.store or field.column:
|
||||
|
@ -3007,14 +3001,8 @@ class BaseModel(object):
|
|||
# register stuff about low-level function fields
|
||||
cls._init_function_fields(cls.pool, self._cr)
|
||||
|
||||
# check constraints
|
||||
for func in cls._constraint_methods:
|
||||
if not all(name in cls._fields for name in func._constrains):
|
||||
_logger.warning("@constrains%r parameters must be field names", func._constrains)
|
||||
for name in cls._onchange_methods:
|
||||
if name not in cls._fields:
|
||||
func = cls._onchange_methods[name]
|
||||
_logger.warning("@onchange%r parameters must be field names", func._onchange)
|
||||
# register constraints and onchange methods
|
||||
cls._init_constraints_onchanges()
|
||||
|
||||
# check defaults
|
||||
for name in cls._defaults:
|
||||
|
|
Loading…
Reference in New Issue