From 2f06adde9c46be73d2fbf13a9cfd6b333117e395 Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Tue, 13 Jan 2015 17:36:50 +0100 Subject: [PATCH] [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. --- openerp/models.py | 74 ++++++++++++++++++++++------------------------- 1 file changed, 34 insertions(+), 40 deletions(-) diff --git a/openerp/models.py b/openerp/models.py index 78b6aaaaf32..b71b4383412 100644 --- a/openerp/models.py +++ b/openerp/models.py @@ -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():