Saturday, January 21, 2017

Caching: static cache and database cache

You have to cache results of heavy functions, sql queries and markup if it's possible because it reduces load on a system in general. If you have a block which renders a lot of items shiped from a database - cache it. If you have a function that performs heavy calculations and this function is called many times during a script execution - cache a result of this function.

Static cache


It's recommended to implement static cache for functions that are called many times during a script execution. It's easy to do: just store a function result first time when function is called and skip heavy calculation next time and return saved value from a static variable.
<?php

/**
 * Some function performs heavy calculations.
 *
 * @return mixed
 *   A result.
 */
function module_heavy_function() {
  // Function drupal_static() returns
  // a static variable by name. Usually
  // variable name equals a function
  // name.
  $result = &drupal_static(__FUNCTION__);

  if (!isset($result)) {
    // Perform heavy calculation here.
    ...

    // After that assign result to a
    // static variable.
    $result = $result_of_heavy_calculations;
  }

  return $result;
}

Database cache


If you want to save a function result for some period of time you have to implement database cache. You can specify a cache lifetime (when it will be expired) or invalidate cache manually when do you need.
<?php

/**
 * Some function performs heavy calculations.
 *
 * @return mixed
 *   A result.
 */
function module_heavy_function() {
  $cache_name = 'module:module_heavy_function';
  $result_of_heavy_calculations = NULL;

  // Cache miss: If there is no cached data or
  // cache have expired or you invalidated cache
  // manually do heavy calculations and save
  // a result into a cache.
  if (!cache_get($cache_name)) {
    // Perform heavy calculation here.
    ...

    // After that set cache. Data will be saved
    // into cache bin 'cache' for one hour.
    cache_set($cache_name, $result_of_heavy_calculations, 'cache', time() + 60 * 60);
  }
  // Cache hit: load cached data from a database
  // and return it.
  else {
    $cache = cache_get($cache_name);
    $result_of_heavy_calculations = $cache->data;
  }

  return $result_of_heavy_calculations;
}
Manual cache invalidating:
<?php

// You can invalidate all cached data
// that matches a wildcard cid 'module:*';
cache_clear_all('module:', 'cache', TRUE);

// Or you can invalidate cache by specific
// cid.
cache_clear_all('module:content', 'cache');
You can also cache a data of a renderable array by specifying #cache key.
<?php

$renderable_array['content'] = [
  '#cache' => [
    'cid' => 'module:content',
    'bin' => 'cache',
    'expire' => time() + 60 * 60,
  ],
  '#markup' => 'This markup will be cached',
];

Key notes:

3 comments:

  1. Excellent article, it helped me solve one of the business problems in my new project. Often, I prefer to solve such problems with the help of outsourcing http://www.nixsolutions.com/departments/php/. This is a guarantee of quality development and completion of the project on time, but there are situations that can be solved independently, as some issues are not difficult.

    ReplyDelete
  2. After reading your article, I finally completed some tasks and solved the problems related to one project http://www.intellias.com/

    ReplyDelete