[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
This commit is contained in:
Julien Castiaux
2021-06-11 17:09:05 +00:00
parent 5815ce7753
commit c0ab436723
+14 -7
View File
@@ -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):