[IMP] base: prefetch actions models in batch during /web menus loading

Gain of ~80% of the SQL queries & ~50% of execution time in a database
with test_main_flows & dependencies installed.

On a benchmark of 100 calls of (load_menus(True) + load_menus(False))

* 266 > 56 queries
* 0.38 > 0.21 sec of execution (mean)

Note that this only impacts the first request since this method is cached.
Unless user groups (or debug status) are different, the cached results
are returned.

closes odoo/odoo#83172

Signed-off-by: Raphael Collet <rco@odoo.com>
This commit is contained in:
Victor Feyens
2022-02-08 11:07:50 +00:00
committed by Raphael Collet
parent d369c1304f
commit a2991e458c
+15 -7
View File
@@ -2,6 +2,7 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import base64
from collections import defaultdict
import operator
import re
@@ -93,15 +94,22 @@ class IrUiMenu(models.Model):
# process action menus, check whether their action is allowed
access = self.env['ir.model.access']
MODEL_GETTER = {
'ir.actions.act_window': lambda action: action.res_model,
'ir.actions.report': lambda action: action.model,
'ir.actions.server': lambda action: action.model_id.model,
MODEL_BY_TYPE = {
'ir.actions.act_window': 'res_model',
'ir.actions.report': 'model',
'ir.actions.server': 'model_name',
}
# performance trick: determine the ids to prefetch by type
prefetch_ids = defaultdict(list)
for action in action_menus.mapped('action'):
prefetch_ids[action._name].append(action.id)
for menu in action_menus:
get_model = MODEL_GETTER.get(menu.action._name)
if not get_model or not get_model(menu.action) or \
access.check(get_model(menu.action), 'read', False):
action = menu.action
action = action.with_prefetch(prefetch_ids[action._name])
model_name = action._name in MODEL_BY_TYPE and action[MODEL_BY_TYPE[action._name]]
if not model_name or access.check(model_name, 'read', False):
# make menu visible, and its folder ancestors, too
visible += menu
menu = menu.parent_id