Please note, that this is an advanced topic. Blindly following the advice given here will potentially render a site insecure and might lead to data leaks.

One of the most important metrics when dealing with caching data is the cache-hit ratio. An efficient setup delivers most of the content from cache and only rebuilds individual items when they changed. Regrettably the caching policy implemented in Drupal core is not that smart. In fact the whole page cache is cleared whenever any content is changed. Additionally all pages are swiped from cache during every cron run.

While the problems outlined above are common for all Drupal installations, Authcache contributes a couple of very distinct aspects. In order to prevent leaking data, Authcache stores different variants of one and the same page for every distinct combination of roles. Authcache is therefore only effective when a site has many users with the exact same combination of roles.

In the following some techniques are discussed to increase cache-hit ratios.

Minimum cache lifetime and expiration of cached pages

The settings under Administration » Configuration » Development » Performance often are a source of confusion. Some good explanations can be found on the web. E.g. on Phase2 Blog:

Minimum cache lifetime is often misinterpreted as meaning "pages will be regenerated after this much time has passed". What it actually means is that pages will not be regenerated until at least this much time has passed and a cache clearing event has happened. I’ll discuss cache clearing events after covering expiration of cached pages.

Expiration of cached pages is also sometimes misinterpreted. This value controls what is sent as a max-age value in a Cache-Control header and thus advises proxy servers how long they may serve the page without asking your Drupal install for a new copy. This does not mean that the page will be regenerated after this much time, it just means that the proxy server must check back with Drupal to see if a new version of the page exists after this much time. Drupal will only regenerate a page after a cache clearing event occurs.

There is also a helpful article in the Pantheon Support Center.

It should be noted that Expiration of cached pages not only influences how long a proxy server will keep and serve a cached copy, it also applies to the browser cache. Also note that the setting Minimum cache lifetime only has a positive effect when content on a site is changing in high rates.

Prevent clearing cache on cron run

In order to prevent cache swipes on every cron run, set up a module capable of running individual cron-hooks on different rates. E.g. Elysia Cron. Make sure that system_cron does not run more than once a day. Alternatively disable system_cron completely and break it up into two separate cron hooks implemented in a custom module. Then run the filesystem-housekeeping-part at a different rate than the cache-swiping one.

Extended page cache lifetimes and Ajax forms

For sites with Ajax forms, it is necessary to extend the lifetime of form-cache entries if pages could be cached for more than 6 hours. The Authcache Form module provides this functionality if the Cache Object API module is installed and configured for the form-cache bin. The following settings.php-snipped enables flexible expiry times for form-cache entries:

# Include the Cache Object API Wrapper as a cache backend
$conf['cache_backends'][] = 'sites/all/modules/cacheobject/cacheobject.inc';
# Set the cache class for the form cache to
$conf['cache_class_cache_form'] = 'CacheObjectAPIWrapper';
# Optionally set the underlying cache class
$conf['cacheobject_class_cache_form'] = 'DrupalDatabaseCache';

Customizing authcache key calculation

When selecting the appropriate variant of a page a user should be served, Authcache examines characteristic properties of the currently logged in user. Modules may supply additional key-value pairs by implementing hook_authcache_key_properties. The implementation in authcache.module looks something like this:

/**
 * Implements hook_authcache_key_properties().
 */
function authcache_authcache_key_properties() {
  global $user, $base_url;

  // Remove "authenticated user"-role from the account roles except when it is
  // the only role on the account.
  $account_roles = $user->roles;
  if (array_keys($account_roles) != array(DRUPAL_AUTHENTICATED_RID)) {
    unset($account_roles[DRUPAL_AUTHENTICATED_RID]);
  }

  $roles = array_keys($account_roles);
  sort($roles);

  return array(
    'base_url' => $base_url,
    'roles' => $roles,
  );
}

On a site having many roles with identical permissions, or where differing permissions will not influence the markup of cached pages, it might be feasible to override this mechanism by implementing hook_authcache_key_properties_alter in a custom module.

See #2105203-2: Possible to exclude certain roles from authcache key? Share caches between more users for an example.

Comments

delta’s picture

For those like me who want to have two different cache for anonymous based on the server request, you should use the following:

in settings.php

include_once 'sites/all/modules/custom/your_module/your_module.cache.inc';
$conf['authcache_key_generator'] = 'your_module_authcache_anonymous_key_generator';

in your module cache.inc


/**
 * Return the key suitable for this request if no session is open.
 */
function your_module_authcache_anonymous_key_generator() {
  global $base_root;

  $key = $base_root;
  if ($_SERVER['HTTP_USER_AGENT'] == 'whatever') {
    $key .= '::whatever';
  }

  return $key;
}