## Description
### Problem/Motivation
After upgrading from Drupal 10.5.4 to 10.5.6, we noticed severe performance degradation on node/edit pages. XHProf profiling revealed that `MetatagManager::sortedTags()` and `MetatagManager::sortedGroups()` are being called hundreds of times per request, each time re-sorting all metatag definitions.
#### XHProf Comparison Data
| Metric | Drupal 10.5.4 | Drupal 10.5.6 | Increase |
|--------|---------------|---------------|----------|
| Total Wall Time | 3.83 sec | 6.08 sec | +58% |
| SortArray::sortByKeyInt calls | 42,694 | 1,025,349 | 24x |
| SortArray::sortByWeightElement calls | 42,668 | 1,025,323 | 24x |
| uasort calls | 673 | 19,438 | 29x |
#### Root Cause
The `sortedTags()` and `sortedGroups()` methods in `MetatagManager` have no caching. Every call recomputes the sorted arrays by:
1. Getting all tag/group definitions
2. Iterating through them
3. Calling `uasort()` with `SortArray::sortByWeightElement`
This was always inefficient, but became critical after Drupal core 10.5.5/10.5.6 changes to entity revision queries (Issues #3548313 and #3555720), which appear to trigger more computed field evaluations during form processing.
### Steps to reproduce
1. Install Drupal 10.5.6 with Metatag 2.x
2. Also add paragraph module with nested paragraphs (not tried without paragraphs module but could be existing there as well.)
3. Create a content type with a metatag field
4. Enable XHProf profiling
5. Visit the node/add or node/edit page
6. Observe excessive calls to `sortByWeightElement` and `sortByKeyInt`
### Proposed resolution
Add instance-level caching to `sortedTags()` and `sortedGroups()` methods. Since the tag and group definitions don't change during a request, the sorted results can be cached after the first computation.
### Patch summary
1. Add two protected cache properties: `$sortedGroupsCache` and `$sortedTagsCache`
2. Modify `sortedGroups()` to return cached result if available
3. Modify `sortedTags()` to return cached result if available
### Expected improvement
| Metric | Before Patch | After Patch |
|--------|--------------|-------------|
| sortByKeyInt calls | 1,025,349 | ~1,300 |
| sortByWeightElement calls | 1,025,323 | ~1,300 |
| Wall time saved | - | ~1-2 seconds |
| Comment | File | Size | Author |
|---|---|---|---|
| #4 | metatag-3577367-232.patch | 2.41 KB | moneeshk |
Issue fork metatag-3577367
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
damienmckennaThat's an incredible improvement, thank you. We'll definitely get it into 2.2.x and likely add it to 2.1.x too.
Comment #4
moneeshk commentedUploaded the patch file
Comment #5
guptahemant commentedComment #8
damienmckennaCommitted. Thank you!