From a2991e458c401d744b70048b77d47e5829204a6b Mon Sep 17 00:00:00 2001 From: Victor Feyens Date: Thu, 20 Jan 2022 14:40:25 +0000 Subject: [PATCH] [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 --- odoo/addons/base/models/ir_ui_menu.py | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/odoo/addons/base/models/ir_ui_menu.py b/odoo/addons/base/models/ir_ui_menu.py index a77d4971fe4..d6c3e46c72e 100644 --- a/odoo/addons/base/models/ir_ui_menu.py +++ b/odoo/addons/base/models/ir_ui_menu.py @@ -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