Change record status: 
Project: 
Introduced in branch: 
11.2.x
Introduced in version: 
11.2.x
Description: 

Cache tags of fetched cache entries need to be verified to ensure that they are still valid. The implementation for cache tag validation is quite optimized with a static cache and support for checking multiple cache tags at once, but still, each cache item that contains at least one not-yet-seen cache tag for the current request results in an additional lookup.

A new ability to register cache tags for preloading allows to define that certain cache tags are used on most pages and should be loaded upfront with the first cache tag, this can significantly reduce the amount of lookups necessary on pages with warm render caches.

Cache tag checksum implementations can now implement the new interface \Drupal\Core\Cache\CacheTagsChecksumPreloadInterface which defines the method registerCacheTagsForPreloadmethod. This method is already implemented in the recommended \Drupal\Core\Cache\CacheTagsChecksumTrait, no further change is required when using relying on that trait.

The new \Drupal\Core\Cache\EventSubscriber\CacheTagPreloadSubscriber automatically registers the following cache tags on all request for preloading:

[
  'route_match',
  'access_policies',
  'routes',
  'router',
  'entity_types',
  'entity_field_info',
  'entity_bundles',
  'local_task',
  'library_info',
]

Modules and sites may either implement their own code to register more cache tags or use the included setting:

$settings['cache_preload_tags'] = ['additional_cache_tag'];

The target audience for further optimizations are sites with a large amount of requests as well as sites using multiple servers where the cost of cache lookups tends to be higher.

Good targets for such preloading are tags that are often used and allow to eliminate entire lookups, as shown in following assertions for the StandardPerformanceTest request:

-      'CacheTagLookupQueryCount' => 29,
+      'CacheTagLookupQueryCount' => 22,
       'CacheTagGroupedLookups' => [
-        ['route_match'],
-        ['entity_types'],
-        ['routes'],
+        ['route_match', 'access_policies', 'routes', 'router', 'entity_types', 'entity_field_info', 'entity_bundles', 'local_task', 'library_info'],
         ['config:views.view.frontpage'],
         ['config:core.extension', 'views_data'],
-        ['entity_field_info'],
-        ['entity_bundles'],
-        ['node_values'],
         ['node:1', 'node_list'],
-        ['user_values'],
         ['rendered', 'user:0', 'user_view'],
         ['config:filter.format.restricted_html', 'node_view'],
         ['block_view', 'config:block.block.stark_site_branding', 'config:system.site'],
@@ -167,14 +162,12 @@ protected function testAnonymous(): void {
         ['config:block.block.stark_breadcrumbs'],
         ['config:block.block.stark_primary_admin_actions'],
         ['config:block.block.stark_messages'],
-        ['local_task'],
         ['config:block.block.stark_primary_local_tasks'],
         ['config:block.block.stark_secondary_local_tasks'],
         ['config:block.block.stark_help'],
         ['config:block.block.stark_powered'],
         ['config:block.block.stark_syndicate'],
         ['config:block.block.stark_content', 'config:block.block.stark_page_title', 'config:block_list', 'http_response'],
-        ['library_info'],
         ['config:user.role.anonymous'],
       ],

In this scenario, sites that frequently use views might want to add ['config:core.extension', 'views_data'], but there is little benefit to adding rendered or user_view as it is combined with many different user ids and a query is then still necessary.

Additional notes:

  • When using Redis, cache tag lookups can be investigated using redis-cli MONITOR | grep :cachetags:, otherwise a debugger or profiling tool can be used.
  • Impacts: 
    Module developers