[IMP] base, mail: cache user.has_group() + ir.ui.menu.load*()

Loading the menus is the most expensive
operation for an average page load, and
the result does not change often.
The menu filtering already uses a separate
cache based on groups, but the rest of the
loading includes reading actions and
translating menu names, which is also
expensive.

Added a cache keyed on user + user
lang, plus relevant cache invalidation
when any of the following are touched:
access rights, user data including
groups and language, menus or mail.group
subscriptions.

The menu filtering cache is still
useful in parallel has it is invalidated
under different conditions.

User.has_group() is cheap but still
called very often, so it is an easy
win as well, and also frequently
used when rendering page templates.
This commit is contained in:
Olivier Dony 2014-07-17 17:18:14 +02:00
parent 68aa292f0a
commit 15174e9a70
3 changed files with 18 additions and 2 deletions

View File

@ -1660,7 +1660,10 @@ class mail_thread(osv.AbstractModel):
if user_ids is None:
user_ids = [uid]
partner_ids = [user.partner_id.id for user in self.pool.get('res.users').browse(cr, uid, user_ids, context=context)]
return self.message_subscribe(cr, uid, ids, partner_ids, subtype_ids=subtype_ids, context=context)
result = self.message_subscribe(cr, uid, ids, partner_ids, subtype_ids=subtype_ids, context=context)
if partner_ids and result:
self.pool['ir.ui.menu'].clear_cache()
return result
def message_subscribe(self, cr, uid, ids, partner_ids, subtype_ids=None, context=None):
""" Add partners to the records followers. """
@ -1720,7 +1723,10 @@ class mail_thread(osv.AbstractModel):
if user_ids is None:
user_ids = [uid]
partner_ids = [user.partner_id.id for user in self.pool.get('res.users').browse(cr, uid, user_ids, context=context)]
return self.message_unsubscribe(cr, uid, ids, partner_ids, context=context)
result = self.message_unsubscribe(cr, uid, ids, partner_ids, context=context)
if partner_ids and result:
self.pool['ir.ui.menu'].clear_cache()
return result
def message_unsubscribe(self, cr, uid, ids, partner_ids, context=None):
""" Remove partners from the records followers. """

View File

@ -53,6 +53,8 @@ class ir_ui_menu(osv.osv):
# but since we do not use it, set it by ourself.
self.pool._any_cache_cleared = True
self._menu_cache.clear()
self.load_menus_root._orig.clear_cache(self)
self.load_menus._orig.clear_cache(self)
@api.multi
@api.returns('self')
@ -352,6 +354,8 @@ class ir_ui_menu(osv.osv):
menu_domain = [('parent_id', '=', False)]
return self.search(cr, uid, menu_domain, context=context)
@api.cr_uid_context
@tools.ormcache_context(accepted_keys=('lang',))
def load_menus_root(self, cr, uid, context=None):
fields = ['name', 'sequence', 'parent_id', 'action']
menu_root_ids = self.get_user_roots(cr, uid, context=context)
@ -364,6 +368,9 @@ class ir_ui_menu(osv.osv):
'all_menu_ids': menu_root_ids,
}
@api.cr_uid_context
@tools.ormcache_context(accepted_keys=('lang',))
def load_menus(self, cr, uid, context=None):
""" Loads all menu items (all applications and their sub-menus).

View File

@ -126,6 +126,7 @@ class res_groups(osv.osv):
_('The name of the group can not start with "-"'))
res = super(res_groups, self).write(cr, uid, ids, vals, context=context)
self.pool['ir.model.access'].call_cache_clearing_methods(cr)
self.pool['res.users'].has_group.clear_cache(self.pool['res.users'])
return res
class res_users(osv.osv):
@ -329,6 +330,7 @@ class res_users(osv.osv):
if id in self._uid_cache[db]:
del self._uid_cache[db][id]
self.context_get.clear_cache(self)
self.has_group.clear_cache(self)
return res
def unlink(self, cr, uid, ids, context=None):
@ -511,6 +513,7 @@ class res_users(osv.osv):
'target': 'new',
}
@tools.ormcache(skiparg=2)
def has_group(self, cr, uid, group_ext_id):
"""Checks whether user belongs to given group.