diff options
| author | Raphael Collet <rco@odoo.com> | 2019-08-27 09:51:04 +0000 |
|---|---|---|
| committer | Raphael Collet <rco@odoo.com> | 2019-09-09 13:18:48 +0000 |
| commit | cfb08e87b0fa8895ec4406c9b30d2ebdb790e346 (patch) | |
| tree | 4ac1ff2d8a34e3fb215dfb6b562f287fea71bf34 /odoo/modules | |
| parent | 3d2df88ffd5cfb9644bc54744a6c9b9a7fcfc264 (diff) | |
[FIX] models: use transitive triggers instead of recursion
On average, this reduces the total time spent in method `modified` by
half (times measured on invoice creation and post).
Diffstat (limited to 'odoo/modules')
| -rw-r--r-- | odoo/modules/registry.py | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/odoo/modules/registry.py b/odoo/modules/registry.py index c3930d3f425..8a70b8d7582 100644 --- a/odoo/modules/registry.py +++ b/odoo/modules/registry.py @@ -247,6 +247,49 @@ class Registry(Mapping): for model in models: model._setup_fields() + # determine field dependencies + Model = odoo.models.Model + dependencies = { + field: set(field.resolve_depends(model)) + for model in models + if isinstance(model, Model) + for field in model._fields.values() + } + + # determine transitive dependencies + def transitive_dependencies(field, seen=[]): + if field in seen: + return + for seq1 in dependencies[field]: + yield seq1 + for seq2 in transitive_dependencies(seq1[-1], seen + [field]): + yield concat(seq1[:-1], seq2) + + def concat(seq1, seq2): + if seq1 and seq2: + f1, f2 = seq1[-1], seq2[0] + if f1.type == 'one2many' and f2.type == 'many2one' and \ + f1.model_name == f2.comodel_name and f1.inverse_name == f2.name: + return concat(seq1[:-1], seq2[1:]) + return seq1 + seq2 + + # determine triggers based on transitive dependencies + triggers = {} + for field in dependencies: + for path in transitive_dependencies(field): + if path: + tree = triggers + for label in reversed(path): + tree = tree.setdefault(label, {}) + tree.setdefault(None, set()).add(field) + + self.field_triggers_create = triggers + self.field_triggers = { + field: tree + for field, tree in triggers.items() + if not (field.type == 'one2many' and field.inverse) + } + for model in models: model._setup_complete() |
