From c0ab436723f70f625e09390978bd0b668ee1a67c Mon Sep 17 00:00:00 2001 From: Julien Castiaux Date: Tue, 1 Jun 2021 16:41:56 +0000 Subject: [PATCH] [IMP] base: fast special cases in node modifiers The parsing of the values of attributes `attrs`, `states`, `invisible`, `readonly` and `required` is done many times during the post-processing of a view. The functions `ast.literal_eval` and `safe_eval`, although being pretty cheap, are called so many times that they represent about 10% of the time spent in `field_view_get()`. The variables of the function were poorly named, we take this commit opportunity to rename them: `a` => `attr`, `v` => `value`. After analysis of what was evaluated, it turned out that 95% of the expressions safe-evaluated were '1', '0', 'True' and 'False'. We introduced the special cases to quickly bypass the evaluation and speed up the rendering. Using our benchmark (render_all_view test-tag with website_sale, mrp, contacts, crm and timesheet installed) the runtimes are 27.58s without this commit and 27.45s with. Task: 2495504 --- odoo/addons/base/models/ir_ui_view.py | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/odoo/addons/base/models/ir_ui_view.py b/odoo/addons/base/models/ir_ui_view.py index 2d783475c45..0c47a7aa512 100644 --- a/odoo/addons/base/models/ir_ui_view.py +++ b/odoo/addons/base/models/ir_ui_view.py @@ -74,18 +74,25 @@ def transfer_node_to_modifiers(node, modifiers, context=None, current_node_path= else: modifiers['invisible'] = [('state', 'not in', node.get('states').split(','))] - for a in ('invisible', 'readonly', 'required'): - if node.get(a): - v = bool(safe_eval.safe_eval(node.get(a), {'context': context or {}})) + for attr in ('invisible', 'readonly', 'required'): + value_str = node.get(attr) + if value_str: + # most (~95%) elements are 0/1/True/False + if value_str == '1' or value_str == 'True': + value = True + elif value_str == '0' or value_str == 'False': + value = False + else: + value = bool(safe_eval.safe_eval(value_str, {'context': context or {}})) node_path = current_node_path or () - if 'tree' in node_path and 'header' not in node_path and a == 'invisible': + if 'tree' in node_path and 'header' not in node_path and attr == 'invisible': # Invisible in a tree view has a specific meaning, make it a # new key in the modifiers attribute. - modifiers['column_invisible'] = v - elif v or (a not in modifiers or not isinstance(modifiers[a], list)): + modifiers['column_invisible'] = value + elif value or (attr not in modifiers or not isinstance(modifiers[attr], list)): # Don't set the attribute to False if a dynamic value was # provided (i.e. a domain from attrs or states). - modifiers[a] = v + modifiers[attr] = value def simplify_modifiers(modifiers):