Problem/Motivation
Found when profiling serialization of about 1,800 entities via a drush command.
TypedDataManager::getPropertyInstance() is called by entity ::getTranslatedField().
We already do some static caching of instances based on the object and root definition. However even generating that cache key can be expensive due to lots of calls to EntityDataDefinition::getDataType().
On the drush command I'm testing, there were 176k calls to that, taking 184ms.
By additionally static caching that calls, we can cut about 181ms off that time.
While I don't think we'll see much if any benefit for 'normal' requests, any list of similar entities with lots of fields will have at least some duplication here.
Steps to reproduce
Proposed resolution
Remaining tasks
User interface changes
Introduced terminology
API changes
Data model changes
Release notes snippet
| Comment | File | Size | Author |
|---|---|---|---|
| #8 | Screenshot 2026-06-21 at 10.57.56.png | 148.44 KB | catch |
| #8 | Screenshot 2026-06-21 at 10.58.03.png | 150.05 KB | catch |
| #6 | Screenshot from 2026-06-19 08-14-12.png | 503.21 KB | catch |
| #5 | Screenshot from 2026-06-19 07-56-13.png | 490.76 KB | catch |
| #5 | Screenshot from 2026-06-19 07-56-18.png | 485.14 KB | catch |
Issue fork drupal-3604100
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 #2
catchComment #4
nicxvan commentedlol.
Is there a script I can use to replicate this?
Comment #5
catchYou can see it on the front page of umami, if you do
TRUNCATE cache_render; TRUNCATE cache_dynamic_page_cache;first.It is very non-dramatic but it's visible. Attaching xhgui screenshots of that.
Comment #6
catchLooking more, I think we can do similar for ::getRoot() since the $object passed in is often identical. Can use the same SplObjectStorage.
Pushing a commit and attaching another screenshot. This halves the calls to TypedData::getRoot() on the Umami front page.
This appears to get inclusive wall time for TypedDataManager::getPropertyInstance() down from 32ms to about 25ms (with cold render and dynamic page caches).
Comment #7
catchFound a memory leak - SplObjectStorage counts as a reference to the object, we can just cap the number of items at 3000 and flush it when a new root object is provided if it's over that number. Tested with the client-specific drush command it still helped a lot.
Comment #8
catchSwitched from the SplObjectStorage + cap approach to a WeakMap, and WeakMap works great.
Getting about 2 seconds off an 8 second drush command (same as raw SplObjectStorage approach, seems to be identical performance) as well as a ~15mb reduction in memory usage from 58mb to 43mb. The memory usage reduction isn't the weakmap itself, but the work we're saving reducing memory usage while the weakmap means the memory requirement from the new approach is minimal.