[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 # basic setup of field
field.set_class_name(cls, name) field.set_class_name(cls, name)
if field.store or field.column: # cls._columns will be updated once fields are set up
cls._columns[name] = field.to_column()
else:
# remove potential column that may be overridden by field
cls._columns.pop(name, None)
@classmethod @classmethod
def _pop_field(cls, name): def _pop_field(cls, name):
@ -605,13 +601,6 @@ class BaseModel(object):
# inferred metadata; use its ancestor instead # inferred metadata; use its ancestor instead
parent_class = type(parent_model).__base__ 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 = dict(parent_class._inherits)
inherits.update(cls._inherits) inherits.update(cls._inherits)
@ -635,7 +624,6 @@ class BaseModel(object):
attrs = { attrs = {
'_name': name, '_name': name,
'_register': False, '_register': False,
'_columns': columns,
'_inherits': inherits, '_inherits': inherits,
'_depends': depends, '_depends': depends,
'_constraints': constraints, '_constraints': constraints,
@ -648,7 +636,7 @@ class BaseModel(object):
attrs = { attrs = {
'_name': name, '_name': name,
'_register': False, '_register': False,
'_columns': dict(cls._columns), '_columns': {}, # filled by _setup_fields()
'_defaults': {}, # filled by Field._determine_default() '_defaults': {}, # filled by Field._determine_default()
'_inherits': dict(cls._inherits), '_inherits': dict(cls._inherits),
'_depends': dict(cls._depends), '_depends': dict(cls._depends),
@ -2874,18 +2862,12 @@ class BaseModel(object):
# #
@classmethod @classmethod
def _inherits_reload(cls): def _init_inherited_fields(cls):
""" Recompute the _inherit_fields mapping, and inherited fields. """ """ Determine inherited fields. """
struct = {} # determine candidate inherited fields
fields = {} fields = {}
for parent_model, parent_field in cls._inherits.iteritems(): for parent_model, parent_field in cls._inherits.iteritems():
parent = cls.pool[parent_model] 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(): for name, field in parent._fields.iteritems():
fields[name] = field.new( fields[name] = field.new(
inherited=True, inherited=True,
@ -2893,15 +2875,25 @@ class BaseModel(object):
related_sudo=False, 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 # add inherited fields that are not redefined locally
for name, field in fields.iteritems(): for name, field in fields.iteritems():
if name not in cls._fields: if name not in cls._fields:
cls._add_field(name, field) 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 @classmethod
def _get_column_infos(cls): def _get_column_infos(cls):
"""Returns a dict mapping all fields names (direct fields and """Returns a dict mapping all fields names (direct fields and
@ -2918,14 +2910,16 @@ class BaseModel(object):
@classmethod @classmethod
def _inherits_check(cls): def _inherits_check(cls):
for table, field_name in cls._inherits.items(): 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) _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, from .fields import Many2one
required=True, ondelete="cascade") field = 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"): 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) _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 field.required = True
cls._columns[field_name].ondelete = "cascade" field.ondelete = "cascade"
# reflect fields with delegate=True in dictionary cls._inherits # reflect fields with delegate=True in dictionary cls._inherits
for field in cls._fields.itervalues(): for field in cls._fields.itervalues():
@ -2967,17 +2961,17 @@ class BaseModel(object):
# retrieve inherited fields # retrieve inherited fields
cls._inherits_check() cls._inherits_check()
cls._inherits_reload() cls._init_inherited_fields()
# set up fields # set up fields, and update their corresponding columns
for field in cls._fields.itervalues():
field.setup(self.env)
# update columns (fields may have changed)
for name, field in cls._fields.iteritems(): 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() 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 # group fields by compute to determine field.computed_fields
fields_by_compute = defaultdict(list) fields_by_compute = defaultdict(list)
for field in cls._fields.itervalues(): for field in cls._fields.itervalues():