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.
Using and reusing online examples from the drupal community.
- 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