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:

2 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