[IMP] models: speedup registry loading (35% less time)

The field setup on models is improved: only fields are determined when building
the model's class; the final _columns is computed from the fields once they are
set up.
This commit is contained in:
Raphael Collet 2015-01-13 17:36:50 +01:00
parent 37e85a1e35
commit 2f06adde9c
1 changed files with 34 additions and 40 deletions

View File

@ -481,11 +481,7 @@ class BaseModel(object):
# basic setup of field
field.set_class_name(cls, name)
if field.store or field.column:
cls._columns[name] = field.to_column()
else:
# remove potential column that may be overridden by field
cls._columns.pop(name, None)
# cls._columns will be updated once fields are set up
@classmethod
def _pop_field(cls, name):
@ -605,13 +601,6 @@ class BaseModel(object):
# inferred metadata; use its ancestor instead
parent_class = type(parent_model).__base__
# don't inherit custom fields
columns = dict((key, val)
for key, val in parent_class._columns.iteritems()
if not val.manual
)
columns.update(cls._columns)
inherits = dict(parent_class._inherits)
inherits.update(cls._inherits)
@ -635,7 +624,6 @@ class BaseModel(object):
attrs = {
'_name': name,
'_register': False,
'_columns': columns,
'_inherits': inherits,
'_depends': depends,
'_constraints': constraints,
@ -648,7 +636,7 @@ class BaseModel(object):
attrs = {
'_name': name,
'_register': False,
'_columns': dict(cls._columns),
'_columns': {}, # filled by _setup_fields()
'_defaults': {}, # filled by Field._determine_default()
'_inherits': dict(cls._inherits),
'_depends': dict(cls._depends),
@ -2874,18 +2862,12 @@ class BaseModel(object):
#
@classmethod
def _inherits_reload(cls):
""" Recompute the _inherit_fields mapping, and inherited fields. """
struct = {}
def _init_inherited_fields(cls):
""" Determine inherited fields. """
# determine candidate inherited fields
fields = {}
for parent_model, parent_field in cls._inherits.iteritems():
parent = cls.pool[parent_model]
# old-api struct for _inherit_fields
for name, column in parent._columns.iteritems():
struct[name] = (parent_model, parent_field, column, parent_model)
for name, source in parent._inherit_fields.iteritems():
struct[name] = (parent_model, parent_field, source[2], source[3])
# new-api fields for _fields
for name, field in parent._fields.iteritems():
fields[name] = field.new(
inherited=True,
@ -2893,15 +2875,25 @@ class BaseModel(object):
related_sudo=False,
)
# old-api stuff
cls._inherit_fields = struct
cls._all_columns = cls._get_column_infos()
# add inherited fields that are not redefined locally
for name, field in fields.iteritems():
if name not in cls._fields:
cls._add_field(name, field)
@classmethod
def _inherits_reload(cls):
""" Recompute the _inherit_fields and _all_columns mappings. """
cls._inherit_fields = struct = {}
for parent_model, parent_field in cls._inherits.iteritems():
parent = cls.pool[parent_model]
for name, column in parent._columns.iteritems():
struct[name] = (parent_model, parent_field, column, parent_model)
for name, source in parent._inherit_fields.iteritems():
struct[name] = (parent_model, parent_field, source[2], source[3])
# old-api stuff
cls._all_columns = cls._get_column_infos()
@classmethod
def _get_column_infos(cls):
"""Returns a dict mapping all fields names (direct fields and
@ -2918,14 +2910,16 @@ class BaseModel(object):
@classmethod
def _inherits_check(cls):
for table, field_name in cls._inherits.items():
if field_name not in cls._columns:
field = cls._fields.get(field_name)
if not field:
_logger.info('Missing many2one field definition for _inherits reference "%s" in "%s", using default one.', field_name, cls._name)
cls._columns[field_name] = fields.many2one(table, string="Automatically created field to link to parent %s" % table,
required=True, ondelete="cascade")
elif not cls._columns[field_name].required or cls._columns[field_name].ondelete.lower() not in ("cascade", "restrict"):
from .fields import Many2one
field = Many2one(table, string="Automatically created field to link to parent %s" % table, required=True, ondelete="cascade")
cls._add_field(field_name, field)
elif not field.required or field.ondelete.lower() not in ("cascade", "restrict"):
_logger.warning('Field definition for _inherits reference "%s" in "%s" must be marked as "required" with ondelete="cascade" or "restrict", forcing it to required + cascade.', field_name, cls._name)
cls._columns[field_name].required = True
cls._columns[field_name].ondelete = "cascade"
field.required = True
field.ondelete = "cascade"
# reflect fields with delegate=True in dictionary cls._inherits
for field in cls._fields.itervalues():
@ -2967,17 +2961,17 @@ class BaseModel(object):
# retrieve inherited fields
cls._inherits_check()
cls._inherits_reload()
cls._init_inherited_fields()
# set up fields
for field in cls._fields.itervalues():
field.setup(self.env)
# update columns (fields may have changed)
# set up fields, and update their corresponding columns
for name, field in cls._fields.iteritems():
if field.column:
field.setup(self.env)
if field.store or field.column:
cls._columns[name] = field.to_column()
# determine old-api cls._inherit_fields and cls._all_columns
cls._inherits_reload()
# group fields by compute to determine field.computed_fields
fields_by_compute = defaultdict(list)
for field in cls._fields.itervalues():