Drupal Cache Form



  1. Flush Drupal Cache From Ftp
  2. Drupal Cache Form Tutorial

Marks cache items from all bins with any of the specified tags as invalid. String $tags: The list of tags to invalidate cache items for. Drupal caching tools and their use As mentioned above, the Drupal cache is stored in a database table. However, our content management system distributes cash and divides it into certain segments, each of which is in a separate table with an individual name. Stack Overflow for Teams is a private, secure spot for you and your coworkers to find and share information. Yes, the form cache was disabled. Otherwise the hook would have fired the first time. But this means that the validation handler validates a version of the form other than what was on the actual page seen by the user. This seems like a bug. In Drupal 8, anonymous page caching is enabled by default. There is no option to turn it on or off. To disable caching for development purposes, set the 'Page cache maximum age' to no caching. Page cache maximum age sets the max-age value in the Cache-Control headers that are output by Drupal 8.

  1. 4.6.x includes/bootstrap.inc cache_set()
  2. 4.7.x includes/bootstrap.inc cache_set()
  3. 5.x includes/cache.inc cache_set()
  4. 6.x includes/cache.inc cache_set()
  5. 6.x includes/cache-install.inc cache_set()

Stores data in the persistent cache.

The persistent cache is split up into several cache bins. In the defaultcache implementation, each cache bin corresponds to a database table by thesame name. Other implementations might want to store several bins in datastructures that get flushed together. While it is not a problem for mostcache bins if the entries in them are flushed before their expire time, somemight break functionality or are extremely expensive to recalculate. Theother bins are expired automatically by core. Contributed modules can addadditional bins and get them expired automatically by implementinghook_flush_caches().

The reasons for having several bins are as follows:

  • Smaller bins mean smaller database tables and allow for faster selects andinserts.
  • We try to put fast changing cache items and rather static ones intodifferent bins. The effect is that only the fast changing bins will need alot of writes to disk. The more static bins will also be better cacheablewith MySQL's query cache.

Parameters

$cid:The cache ID of the data to store.

$data:The data to store in the cache. Complex data types will be automaticallyserialized before insertion. Strings will be stored as plain text and arenot serialized. Some storage engines only allow objects up to a maximum of1MB in size to be stored by default. When caching large arrays or similar,take care to ensure $data does not exceed this size.

$bin:(optional) The cache bin to store the data in. Valid core values are:

  • cache: (default) Generic cache storage bin (used for theme registry,locale date, list of simpletest tests, etc.).
  • cache_block: Stores the content of various blocks.
  • cache_bootstrap: Stores the class registry, the system list of modules,the list of which modules implement which hooks, and the Drupal variablelist.
  • cache_field: Stores the field data belonging to a given object.
  • cache_filter: Stores filtered pieces of content.
  • cache_form: Stores multistep forms. Flushing this bin means that someforms displayed to users lose their state and the data already submittedto them. This bin should not be flushed before its expired time.
  • cache_menu: Stores the structure of visible navigation menus per page.
  • cache_page: Stores generated pages for anonymous users. It is flushedvery often, whenever a page changes, at least for every node and commentsubmission. This is the only bin affected by the page cache setting onthe administrator panel.
  • cache_path: Stores the system paths that have an alias.

$expire:(optional) Controls the maximum lifetime of this cache entry. Note thatcaches might be subject to clearing at any time, so this setting does notguarantee a minimum lifetime. With this in mind, the cache should not beused for data that must be kept during a cache clear, like sessions.

Use one of the following values:

  • CACHE_PERMANENT: Indicates that the item should never be removed unlessexplicitly told to using cache_clear_all() with a cache ID.
  • CACHE_TEMPORARY: Indicates that the item should be removed at the nextgeneral cache wipe.
  • A Unix timestamp: Indicates that the item should be kept at least untilthe given time, after which it behaves like CACHE_TEMPORARY.

See also

_update_cache_set()

cache_get()

archiver_get_infoin includes/common.inc
Retrieves a list of all available archivers.
book_menu_subtree_datain modules/book/book.module
Gets the data representing a subtree of the book hierarchy.
CacheClearCase::testClearArrayin modules/simpletest/tests/cache.test
Test clearing using an array.
CacheClearCase::testClearCidin modules/simpletest/tests/cache.test
Test clearing using a cid.
CacheClearCase::testClearWildcardin modules/simpletest/tests/cache.test
Test clearing using wildcard.

File

includes/cache.inc, line 141
Functions and interfaces for cache handling.

Code

Comments

To clear a specific cache item...

alanom commented

...pass $cid and $bin to the misleadingly named cache_clear_all()

Update Link

spuppett commented

Example of using cache in function

alandarev commented

Wrong expire time?

chrisroane commented

Shouldn't the expire time be added to the current time?

Like this:

Logic error

Drupal Cache Form
RogerB commented

cache_set() is being called on every invokation. It should only be called when the data is rebuilt.

Use REQUEST_TIME rather than

drewish commented

Use REQUEST_TIME rather than time().... but yeah you'd need to treat it as a timestamp so 360 would be some time in 1970.

Edit: this was supposed to be a reply to chrisroane's comment but I guess I clicked the wrong reply link.

Good catch!

chrisroane commented

Couldn't Get This to Work

chrisroane commented

The only way I could get the caching to work as expected in a custom function was to also use &drupal_static(__FUNCTION__) ....Below is a simplified version of what I got working:

General Cache Wipe Details

technicalknockout commented

The $expire option CACHE_TEMPORARY says

Indicates that the item should be removed at the next general cache wipe.

How is the next general cache wipe triggered? Is it triggered by cron jobs? Is it triggered every hour or every day?

cron

forestmars commented
Drupal cache form template

@technicalknockout Yes, it happens on cron run by default, so how often depends on what you have cron set to.

General Cache wipe

xeeshangulzar commented

Is there any way that i can wipe cache after some minutes?

Try the Elysia cron module

bfr commented

Try the Elysia cron module for more fine grained control of the cron service. If that is not enough, implement cache_clear_all() or take a look at the code of drupal_flush_all_caches() for more ideas.

Not 100% sure but i think Rules could also do this.

Expire cache with Unix timestamp using strtotime()

sebas5384 commented

Example with strtotime(), maybe for a more clean and easy way for getting a cache to expire in 6 hours:

This way I can have a select form element with values like '+1 hour', '+6 hour', '+1 day', etc...

Cheers!

Very nice and clean example.

cbiggins commented

Poor Documentation

rvelhote commented

This is very lame but the $expire parameter, when set in a form of a Unix timestamp, is ignored if the parameter cache_lifetime set in admin/config/development/performance is not set to X minutes.

This will cause cache_get to return expired entries!

Sadly, the description for the cache_lifetime parameter is incorrect because it mentions 'cached pages' so one would assume that it's applicable to whole pages and not specific cache entries.

This is not documented and should not even happen otherwise it destroys the purpose of setting an expire parameter.

Form

Expire does nothing

rcls commented

I can confirm there is an issue with the $expire parameter. I spent last night testing this issue out with a simple retrieval of data and storing it to the cache and setting the $expire to time() + 300 (5 minutes). I then printed out the time, the time the cache was set and expiration. The time the cache was set and expiration worked fine, but I noticed that even after 30 minutes this cache would still persist.

A simple way to go around this was to check if time() was bigger than the $cache->expire and then clearing out the cid with cache_clear_all(). An example code is below.

if ($cached = cache_get('db

Flush Drupal Cache From Ftp

rakesh.gectcr commented

if ($cached = cache_get('db_index', 'cache')) {
$tables = $cached->data;
}
else {
$tables = drupal_get_schema();
// Setting the data to drupal cache.
cache_set('db_index', $tables, 'cache', CACHE_TEMPORARY);
}

Drupal 8 now has a Dynamic Page Cache. The Page Cache module only works for anonymous users, the Dynamic Page Cache module takes that a step further: it works for any user.

Since April 8, Drupal 8 had its Page Cache enabled by default. Exactly 5 months later, on September 8, the Dynamic Page Cache1 module was added to Drupal 8, and also enabled by default.

What?

The Page Cache module caches fully rendered HTML responses — it assumes only one variant of each response exists, which is only true for anonymous users2. The innovation in 8 on top of 7’s Page Cache is the addition of cache tags, which allow one to use the Page Cache but still have instantaneous updates: no more stale content.

The Dynamic Page Cache module caches mostly rendered HTML responses — because it does not assume only a single variant exists: thanks to cache contexts, it knows the different variants that exist of each part of the page, and thus also of the final (fully assembled) page.During the rendering process, auto-placeholdering ensures that the parts of the page that are too dynamic to cache3 or are simply uncacheable are replaced with placeholders. These placeholders are only rendered at the very last moment. The Dynamic Page Cache module caches the page just before those placeholders are replaced.

So, conceptually speaking:

Page CacheDynamic Page Cache
  • URL
  • URL
  • cache contexts
  • final response
  • cache tags
  • partial response
  • placeholders
  • cache tags

This table also illustrates quite clearly the strengths and weaknesses of both: Page Cache is faster because it contains the final response, unlike Dynamic Page Cache which only contains a partial response, but thanks to that response not yet being personalized it can be used across users.

In other words: Dynamic Page Cache saves us less work, but in doing so, allows us to apply it in many more cases.

Benchmark

Drupal 8’s Page Cache can respond in constant time. So, for anonymous users, Drupal 8 already responds in constant (amortized) time.

With Dynamic Page Cache, Drupal 8 is now able to respond in constant amortized time + the time it takes to render the placeholders. Which means that most parts of most pages can be cached in the constant part (and it doesn’t matter how much content is in there!). The parts of the page that end up as placeholders are the ones you want to optimize, and if possible, avoid. (Also see BigPipe further down.)

On my machine (ab -c1 -n 1000, PHP 5.5.11, Intel Core i7 2.8 GHz laptop, warm caches, 15 nodes with one comment each, 10 of which are listed on the frontpage):

  • Without Dynamic Page Cache
    • Front page: 61.3 ms/request (16 requests/s)
    • node/1: 92.3 ms/request (10.8 requests/s)
  • With Dynamic Page Cache
    • Front page: 38.3 ms/request (26 requests/s)
    • node/1: 73.8 ms/request (13.5 requests/s)

Analysis

The front page only contains a single placeholder (for messages). This makes it is a strong indicator of the lowest response times to expect: roughly 38 ms on my machine.

  • ~38 ms goes to bootstrapping, routing, route access checking, and of course retrieving the cached response from the Dynamic Page Cache.4
  • Compare that with the node/1 case: 35.5 more milliseconds are spent replacing placeholders there. Which means that we do some very expensive rendering there… and that is the comment form.5

As you can see: Dynamic Page Cache actually becomes a helpful assistant while developing: it surfaces the impossible-to-cache-and-expensive-to-render parts of the page!

Note that we do have an issue to make Dynamic Page Cache run much earlier, see more about that below.

Easily tenfold that on actual servers

Drupal Cache Form Tutorial

Form

The above is tested with a concurrency of 1 client, to ignore web server performance (Apache in my case). See e.g. Rasmus Lerdorf’s profiling of the Page Cache.

Win-win

The real beauty is that it’s a win-win: enterprise (Acquia), medium, small, tiny (hobbyist) all win:

  • Enterprise sites get better tunability and reverse proxy/CDN-based hosting even for authenticated users
  • Tiny sites can handle more simultaneous authenticated users, and serve those faster

So my work was sponsored by Acquia, but benefits everyone!

People have been expressing concerns that Drupal 8 has become too complex, that it doesn’t care about site builders anymore, that it is only for enterprises, etc. I think this is a good counterexample — in fact an even stronger one than Page Cache being enabled by default: this was absolutely out of reach for the majority of Drupal 7 sites. Yet every Drupal 8 site will have this enabled by default.
Yes, we added the complexity of cacheability metadata, but that only affects developers — for whom we have good documentation. And most importantly: site builders reap the benefits: they don’t even have to think about this anymore. Manually clearing caches is a thing of the past starting with Drupal 8!

Drupal is very much like LEGO. Until Drupal 8, if you combined too many LEGO blocks, your Drupal site would become very slow. Setting up caching was very often prohibitively complex. Now the LEGO blocks must specify their cacheability metadata. Which allows Drupal to automate a huge portion of “making things fast”.

New possibilities for small sites (and shared hosting)

Smaller sites will be able to handle more authenticated users simultaneously. And have pages be much faster for those users.

Without any configuration.

Without any frustrating searching on the internet.

New possibilities for enterprise sites (and enterprise hosting)

On the other hand of the spectrum, enterprise hosting now gains the ability to tune: if they prefer to running caching infrastructure with enough storage capacity rather than rendering placeholders on the fly (i.e. more storage for less computation), then they can: just override the default configuration for auto-placeholdering conditions.

It also opens the door to — for the first time — caching responses for authenticated users in a CDN.

New possibilities for developers

The addition of cacheability metadata (cache tags, contexts and max-age), allow for greater insight and tooling when analyzing hosting, infrastructure, performance and caching problems. Previously, you had to analyze/debug a lot of code to figure out why something that was cached was not being invalidated when appropriate by said code.

Because it’s now all standardized, we can build better tools — we can even automatically detect likely problems: suspiciously many cache contexts, suspiciously low maximum ages, suspiciously frequent cache tag invalidations…

And finally, it makes it possible to do BigPipe-style rendering, making Drupal 8 the fastest Drupal yet:

Dynamic Page Cache in 8 vs. Authcache in 7

Dynamic Page Cache’s closest comparison in Drupal 7 is the Authcache module. It’s possible to achieve great performance with Authcache in Drupal 7, but it requires a huge amount of work: all code (contrib & custom) must be analyzed to ensure all aspects that cause variations in the output (rendered pages) are taken into account. All of these factors must then be passed to Authcache so that it can calculate its “authcache key” correctly. The “key properties” that you specify there are conceptually similar to Drupal 8’s cache contexts.However, it is very easy to miss anything, because it’s you as a site owner that is responsible for identifying all the variations (and corresponding key properties) across all modules across all pages6. By default, Authcache assumes the only thing that your site varies by, are a site’s base URL and a user’s roles. So unless your site is very simple (for example not even multilingual), you will need an enormous amount of knowledge/research in order to be able to use Authcache.

(For example, Drupal.org — which currently still runs on Drupal 7 — rolled out render caching of comments several months ago. It works very much like Authcache: you must specify the things that cause variations. One aspect (timezone) was forgotten, and it led to rather confusing broken output. If even Drupal.org’s very strong team can get it wrong, then what hope does a team with less expertise have?)

Dynamic Page Cache in 8 simply builds on the existing cacheability metadata concepts and infrastructure. There’s no need for custom hooks. There’s no possibility of something being forgotten as a site owner. It’s the individual modules’ responsibility now — and those modules know far better what they’re doing. The entire “analyze the entire codebase” phase is gone. And of course, Dynamic Page Cache also supports cache tags, so unlike Authcache in Drupal 7, responses cached in Dynamic Page Cache will actually be updated instantaneously.

In Drupal 8.0.0, Dynamic Page Cache runs after bootstrapping, routing and route access checking. Because Authcache makes certain simplifying assumptions, it can run before Drupal 7 has even fully bootstrapped, thus it is much faster most of the time7. We do have an issue to make Dynamic Page Cache run much earlier, which would result in a great speed-up: #2541284 — we will aim to do that in Drupal 8.x.0.

Finally, because it is enabled by default in Drupal 8, Dynamic Page Cache has one enormous advantage: it brings this functionality to all Drupal sites and all Drupal developers. All Drupal developers are thus heavily encouraged to specify the appropriate cache contexts in their code. Which means that Drupal 8 contrib modules will be battle-hardened by many (tens of) thousands of websites, and missing cacheability metadata will be added. Instead of an enormous burden lying on the shoulders of the Authcache site owner, a very small burden lies on the shoulders of every contrib module maintainer (and user). Drupal 8 contrib modules should have integration test coverage with Dynamic Page Cache enabled.

Historical note

Cache-control

Somewhere in mid-February, Dries asked me what the state was of ESI support in Drupal 8, whether partial pre-rendering was possible, and so on. I replied in two ways: in short (No, ESI is not fully supported yet8) and comprehensively, describing how full ESI support was now more feasible than ever, which other exciting things are possible with the render- and caching-related improvements, and so on. That e-mail I sent formed the foundation of Dries’ Making Drupal 8 fly blog post :)

But a side effect of me describing at a high level the exciting new possibilities got me thinking… I had spent a full year working on improving Drupal 8’s performance & cacheability. At that point, cache tags were ~90% done. Thanks to that, it had become clear that enabling page caching by default had finally become within reach (and it effectively happened two months later).

Cache contexts were also getting in better and better shape. What if… I would be able to leverage cache contexts in a similar way I was able to leverage cache tags? Complete cache tag support allowed us to enable page cache by default. What would complete cache context support allow? Cache tags capture data dependencies. Cache contexts capture (request) context dependencies. Cache tags allow for correct invalidations. Anonymous users do not get any variations, so cache tags are sufficient for them. Which means… that cache contexts would allow me to … do page caching, but for all users — i.e. also authenticated ones!

Or: how articulating an answer to a fairly specific question can make one think of other ideas :)

I started experimenting and was blown away by the results of my rough proof and concept patches. I opened the “SmartCache” ([#2429617]) issue and the “finalize cache contexts API&DX/usage, enable a leap forward in performance” ([#2429287]) issue that captured the many, many places where we’d still have to finish cache context support in order to be able to actually do what the experiment describes.

At the same time, I was talking to Fabian Franz. Together with him, I devised an algorithm (and a proof) to make it possible to bubble cache contexts, which is absolutely essential for Dynamic Page Cache.

Fast forward seven months and we’ve fixed many dozens of blockers for Dynamic Page Cache, and have landed Dynamic Page Cache itself, thanks to the hard work of many people!

  1. Originally, it was called Smart Cache. See issue #2429617. ↩︎

  2. Not every site serves the same exact responses to all their anonymous users, but most do. Therefore this is a great default. If your site serves different responses to different anonymous users, then you can just disable that module. The Page Cache therefore operates just like any other simple reverse proxy setup. ↩︎

  3. Because they contain user-specific or session-specific data, i.e. because they have the user or the session cache context associated. ↩︎

  4. That is significantly slower than 7. We still have lots of work ahead in Drupal 8.1, 8.2 etc to make bootstrapping and routing much faster. ↩︎

  5. We’re working on making forms cacheable in #2578855, which should then put the node/1 response time roughly on par with the front page’s response time when using Dynamic Page Cache. ↩︎

  6. And it always varies by the same key on all pages, even if page A only varies by role, and page B varies by role, user, interface language and organic group. So Authcache always varies by the superset of all possible variations across the entire site. Which means that AuthCache will generate many more variations, even unnecessary ones, and will therefore consume much more space in the cache back-end. ↩︎

  7. When a user first logs in, they will get a full bootstrap, so that the user is authenticated. Since the key is the same on all pages (again, see [^5]), it is then able to cache this key per session and reuse it on all future requests, which means that all subsequent requests for this session will be much faster. See _authcache_builtin_cacheinc_cache_key_get(). ↩︎

  8. Technically, Drupal 7 supported ESI, but it was very, very complex, either via drupal_render_cache_set()’s ability to have cache backends modify the markup they’re being asked to cache (in other words: ESI via side effects) which links to custom endpoints in custom code to generate the dynamic content, or via the ESI module, which is complex to use and also requires custom code. “Full support” in my book means that anything can be served over ESI, transparently, without any custom code, code changes or deep technical knowledge. ↩︎