Drupal 8 and cache

Some of all the parts...

By Mikke Schirén / @mikkdroid / d.o: MiSc Developer @ Wunderkraut

Me?

Worked with Drupal since 2005.

Maintainer of some modules including Varnish, Medium etc.

Works with support and hosting.

Thanks

Using and reusing online examples from the drupal community.

Why important right now?

 

Ingredients

  • What are in core now
  • How that works
  • Status of contrib cache modules
  • Work done on dev days 

Cache tags!

Cache tags!

 

From node/1 in a fresh install

X-Drupal-Cache-Tags: block_view config:block.block.bartik_account_menu config:block.block.bartik_breadcrumbs config:block.block.bartik_content config:block.block.bartik_footer config:block.block.bartik_login config:block.block.bartik_main_menu config:block.block.bartik_messages config:block.block.bartik_powered config:block.block.bartik_tools config:block_list config:filter.format.basic_html config:system.menu.account config:system.menu.footer config:system.menu.main config:system.menu.tools config:system.site config:user.role.anonymous node:1 node_view rendered user:1

Cache contexts!

 

From node/1 in a fresh install

X-Drupal-Cache-Contexts: languages:language_interface route.menu_active_trails:account route.menu_active_trails:footer route.menu_active_trails:main route.menu_active_trails:tools theme timezone user.permissions user.roles

Fast by default™

 

(Also, page cache in drupal it's own module)

Cache tables

(bins)

  • cache_bootstrap
  • cache_config
  • cache_data
  • cache_default
  • cache_discovery
  • cache_entity
  • cache_menu
  • cache_render
  • cache_toolbar

 

D7 cache table


+------------+--------------+------+-----+---------+-------+
| Field      | Type         | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+-------+
| cid        | varchar(255) | NO   | PRI |         |       |
| data       | longblob     | YES  |     | NULL    |       |
| expire     | int(11)      | NO   | MUL | 0       |       |
| created    | int(11)      | NO   |     | 0       |       |
| serialized | smallint(6)  | NO   |     | 0       |       |
+------------+--------------+------+-----+---------+-------+

 

D8 cache table

+------------+---------------+------+-----+---------+-------+
| Field      | Type          | Null | Key | Default | Extra |
+------------+---------------+------+-----+---------+-------+
| cid        | varchar(255)  | NO   | PRI |         |       |
| data       | longblob      | YES  |     | NULL    |       |
| expire     | int(11)       | NO   | MUL | 0       |       |
| created    | decimal(14,3) | NO   |     | 0.000   |       |
| serialized | smallint(6)   | NO   |     | 0       |       |
| tags       | longtext      | YES  |     | NULL    |       |
| checksum   | varchar(255)  | NO   |     | NULL    |       |
+------------+---------------+------+-----+---------+-------+

 

D8 cache table

Render cache: Page

​cid: http://cache.dev/node/1:html                                                   tag: block_view comment_list config:block.block.bartik_account_menu config:block.block.bartik_breadcrumbs config:block.block.bartik_content config:block.block.bartik_footer config:block.block.bartik_login config:block.block.bartik_main_menu config:block.block.bartik_messages config:block.block.bartik_powered config:block.block.bartik_tools config:block_list config:filter.format.basic_html config:system.menu.account config:system.menu.footer config:system.menu.main config:system.menu.tools config:system.site node:1 node_view rendered user:1 user_view 

 

D8 cache table

Render cache: Entity

cid: entity_view:node:1:full:bartik:UTC:r.anonymous                                 
tag: comment_list config:filter.format.basic_html node:1 node_view rendered user:1
user_view

 

Working with caching

Set

public function set($cid, $data, $expire = Cache::PERMANENT, array $tags = array());

Like

$this->cacheBackend->set('cache_demo_posts', $posts, CacheBackendInterface::CACHE_PERMANENT, $cahetags);

Get

public function get($cid, $allow_invalid = FALSE);

Like

$this->cacheBackend->get('cache_demo_posts')

Flush

(drupal_flush_all_caches)

d7

  • Empties cache bins
  • Rebuilds the menu cache and theme registries
  • Invokes a hook so that other modules' cache data can be cleared as well.

Flush

(drupal_flush_all_caches)

d8

  • Flushes all persistent caches
  • Resets all variables
  • Rebuilds all data structures
  • and more...

No more

cache_clear_all

Cleaner methods


From \Drupal\Core\Cache\CacheBackendInterface

public function delete($cid);
public function deleteMultiple(array $cids);
public function deleteAll();
public function invalidate($cid);
public function invalidateMultiple(array $cids);
public function invalidateAll();
public function garbageCollection();
public function removeBin();

Cache invalidation or delete?

From the docs:

The new cache API introduces a new way to “remove” a cache item. In addition to the existing delete methods where cache entries are permanently deleted, cache entries can now also be invalidated.

Delete removes it at once

cache()->set('feed_block', REQUEST_TIME + 600);
cache()->get('feed_block');
cache()->delete('feed_block');
cache()->get('feed_block', TRUE);
Returns FALSE

Sometimes something get updated, but it is not needed to clear at once, like feed import displayed in a block.

The cache for the feed block get marked as invalid and is recreated when it could be done, like on a cron run.

Example

cache()->set('feed_block', REQUEST_TIME + 600);
cache()->get('feed_block');
Returns TRUE
cache()->invalidate('feed_block');
cache()->get('feed_block');
Returns FALSE
cache()->get('feed_block', TRUE);
Returns TRUE
cache()->garbageCollection();
cache()->get('foo', TRUE);
Returns FALSE

Example


 /**
  * Clears the posts from the cache.
  */
  function clearPosts() {
    if ($cache = $this->cacheBackend->get('cache_demo_posts')) {
      Cache::invalidateTags(['my_custom_tag', 'node:1']);
      drupal_set_message('Posts have been removed from cache.', 'status');
    }
    else {
      drupal_set_message('No posts in cache.', 'error');
    }
  }

Example

Render array with cache tags and keys


 $dinner = array(
  '#theme' => 'food',
  '#attributes' => array('class' => 'food'),
  '#caption' => 'Spaghetti',
  '#cache' => array(
    'keys' => ['entity_view', 'node', $node->id()],
    'contexts' => ['language'],
    'tags' => ['node:' . $node->id()],
    'max-age' => Cache::PERMANENT,
  ),
  '#pre_render' => array('food_pre_render'),
  '#eat_spaghetti' => 'Yummy',
);

New cache bins created as services

In mymodule.service.yml

services:
  cache.demo:
    class: Drupal\Core\Cache\CacheBackendInterface
    tags:
      - { name: cache.bin }
    factory_method: get
    factory_service: cache_factory
    arguments: [demo]

Easily declared when to use

public static function create(ContainerInterface $container) {
  return new static(
    $container->get('cache.demo')
  );
}

But normaly you would use the default bin for custom and contrib modules

public static function create(ContainerInterface $container) {
  return new static(
    $container->get('cache.default')
  );
}

Example

 

Code from this example https://github.com/upchuk/cache_demo_d8 by Daniel Sipos

Specify cache backend

 

If you want to use something else than the drupal mysql tables for one bin:

 

$settings['cache']['bins']['render'] = 'cache.backend.memcache';

 

Or for settings another default:

 

$settings['cache']['default'] = 'cache.custom';

Status for contrib

Contrib modules for caching i d8, needs help.

Purge

Much work done in 8.x branch, looking promissing, has support for varnish.

 

Memcache

Work done to support cache tags
(RTBC issue: https://www.drupal.org/node/2056373)
 

(Memcache Storage also have 8.x branch - but it has not much code in it yet)

 

Redis

Great work done on dev days.
https://gitub.com/md-systems/redis

Varnish

Dev release 16 april

More?

D8 Accelerate Performance Sprint

 

Really great work has been done in Montpellier

D8 Accelerate Performance Sprint

 

22 closed core issues

3 RTBC

Over 80 issues worked on

Thanks!

Drupal8 cache

By Mikke Schirén

Drupal8 cache

  • 2,065