Problem/Motivation
Thank you for Masquerade Role! Our support staff use it to see the site with a role of the people they help.
The module replaces the current_user service with MasqueradeAccountProxy. Its getRoles() and hasPermission() ask RoleManager::isActive() first, which reads the user's "active" flag through RoleManager::getData() from user.data: one database query on every call, without a static cache. Drupal calls these two methods very often while it builds a page: the user.roles and user.permissions cache contexts of every cached element, every entity access check, every node grant check.
On our site (Drupal 11.4, msqrole 1.0.21) this made 500 to 800 of these queries for an ordinary page of a logged-in user, and more than 5,000 on a page whose render cache was cold. Even a page served from the dynamic page cache still made more than 200, because the cache contexts of its placeholders are resolved on every request. It does not matter whether the user masquerades: the flag is read either way.
Steps to reproduce
- Install the module and log in as any user (no masquerading needed).
- Log the database queries of a page view, for example with
Database::startLog()or the Webprofiler module. - Most of the queries read the table
users_datawithmodule = 'msqrole'andname = 'active'for the same user.
Proposed resolution
RoleManager::getData()reads all msqrole data of a user with one query and keeps it for the rest of the request (keyed by user ID).setData()andremoveData()drop what is kept for that user, so a change made in the same request is read fresh.- A call with a
NULLuser ID keeps its current behaviour.
With this change, a page of a logged-in user on our site made 10 instead of about 220 database queries (dynamic page cache hit), and the pages became about twice as fast (median of 7 interleaved runs, local Docker setup):
| Page | Before | After |
|---|---|---|
| Front page | 249 ms | 121 ms |
| FAQ page | 163 ms | 82 ms |
| Article listing | 281 ms | 141 ms |
| Content page | 319 ms | 111 ms |
| Personal dashboard | 241 ms | 147 ms |
Remaining tasks
Review the MR.
User interface changes
None.
API changes
None.
Data model changes
None.
Text generated with AI
Issue fork msqrole-3630504
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #3
daniel.pernold commentedComment #4
randalv commentedThis definitely should have been improved long ago, good find and thanks for providing a sensible fix!
I'll merge and push a new tag.
Comment #7
daniel.pernold commentedThank you so much, randalv, for the quick review, the kind words and for releasing the fix in 1.0.22 right away! We'll switch to the new release.