## 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 |

CommentFileSizeAuthor
#4 metatag-3577367-232.patch2.41 KBmoneeshk

Issue fork metatag-3577367

Command icon 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

moneeshk created an issue. See original summary.

damienmckenna’s picture

Version: 2.2.0 » 2.2.x-dev
Parent issue: » #3548158: Plan for Metatag 2.2.1

That's an incredible improvement, thank you. We'll definitely get it into 2.2.x and likely add it to 2.1.x too.

moneeshk’s picture

StatusFileSize
new2.41 KB

Uploaded the patch file

guptahemant’s picture

Status: Active » Needs review

damienmckenna changed the visibility of the branch 3577367-performance-add-caching to hidden.

damienmckenna’s picture

Status: Needs review » Fixed

Committed. Thank you!

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.