From c17e0c96d6a5e67ba6c88b2a4347abef11370012 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Bajsarowicz?= Date: Thu, 6 Aug 2026 01:20:01 +0200 Subject: [PATCH] Build cache tag id lists in one array_merge call FilesystemTagAdapter::getIdsMatchingAnyTags() and ::getAllIds() and RedisTagAdapter::getIdsMatchingAnyTags() merged each tag's id list into an accumulator on every iteration, so every iteration copied the whole result built so far. Cleaning the cache by tags walks one iteration per tag, which makes the cost grow with the square of the number of tags. Collect the per-tag lists and merge them once with argument unpacking. The resulting arrays and their order are identical, and the phpcs:ignore annotations for Magento2.Performance.ForeachArrayMerge are no longer needed. --- .../SymfonyAdapters/FilesystemTagAdapter.php | 16 ++++++---------- .../Adapter/SymfonyAdapters/RedisTagAdapter.php | 9 +++------ 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/lib/internal/Magento/Framework/Cache/Frontend/Adapter/SymfonyAdapters/FilesystemTagAdapter.php b/lib/internal/Magento/Framework/Cache/Frontend/Adapter/SymfonyAdapters/FilesystemTagAdapter.php index a29ecf7bafbbb..1335809366091 100644 --- a/lib/internal/Magento/Framework/Cache/Frontend/Adapter/SymfonyAdapters/FilesystemTagAdapter.php +++ b/lib/internal/Magento/Framework/Cache/Frontend/Adapter/SymfonyAdapters/FilesystemTagAdapter.php @@ -180,13 +180,12 @@ public function getIdsMatchingAnyTags(array $tags): array return []; } - $ids = []; + $idsPerTag = []; foreach ($tags as $tag) { - // phpcs:ignore Magento2.Performance.ForeachArrayMerge - $ids = array_merge($ids, $this->getTagIds($tag)); + $idsPerTag[] = $this->getTagIds($tag); } - return array_values(array_unique($ids)); + return array_values(array_unique(array_merge(...$idsPerTag))); } /** @@ -218,7 +217,7 @@ public function getIdsNotMatchingTags(array $tags): array */ private function getAllIds(): array { - $allIds = []; + $idsPerTag = []; $tagFiles = glob($this->tagDirectory . '*'); if ($tagFiles === false) { @@ -227,14 +226,11 @@ private function getAllIds(): array foreach ($tagFiles as $file) { if (is_file($file)) { - $tag = basename($file); - $ids = $this->getTagIds($tag); - // phpcs:ignore Magento2.Performance.ForeachArrayMerge - $allIds = array_merge($allIds, $ids); + $idsPerTag[] = $this->getTagIds(basename($file)); } } - return array_values(array_unique($allIds)); + return array_values(array_unique(array_merge(...$idsPerTag))); } /** diff --git a/lib/internal/Magento/Framework/Cache/Frontend/Adapter/SymfonyAdapters/RedisTagAdapter.php b/lib/internal/Magento/Framework/Cache/Frontend/Adapter/SymfonyAdapters/RedisTagAdapter.php index dc3f9f4433e7a..a725fc4f9e06a 100644 --- a/lib/internal/Magento/Framework/Cache/Frontend/Adapter/SymfonyAdapters/RedisTagAdapter.php +++ b/lib/internal/Magento/Framework/Cache/Frontend/Adapter/SymfonyAdapters/RedisTagAdapter.php @@ -408,19 +408,16 @@ public function getIdsMatchingAnyTags(array $tags): array // Matches Zend's implementation to prevent Redis slowdowns // @see vendor/colinmollenhour/cache-backend-redis/Cm/Cache/Backend/Redis.php line 777-778 if (count($tags) > self::SUNION_CHUNK_SIZE) { - $allIds = []; + $idsPerChunk = []; $chunks = array_chunk($tags, self::SUNION_CHUNK_SIZE); foreach ($chunks as $chunk) { $tagKeys = array_map([$this, 'getTagKey'], $chunk); $chunkIds = $this->redis->sUnion($tagKeys); - $chunkIds = is_array($chunkIds) ? $chunkIds : []; - - // phpcs:ignore Magento2.Performance.ForeachArrayMerge - $allIds = array_merge($allIds, $chunkIds); + $idsPerChunk[] = is_array($chunkIds) ? $chunkIds : []; } - return array_unique($allIds); + return array_unique(array_merge(...$idsPerChunk)); } $tagKeys = array_map([$this, 'getTagKey'], $tags);