2

As we all know, the whole variable table is being cached in the drupal cache system and is being extracted into global $conf variable in each invoke. In one of our production site with the domain module, we are having hard time to keep up with the memory requirement of PHP for the unserialization of this variable from the cache. At this moment, we've assigned 768mb memory to each PHP thread so that the value can be unserialized.

We are doing the following to fight this:

  1. First of all, we have installed the memcache module to move the cache storage from DB to memory

  2. We have edited memcache module's cache_get and cache_set functions like below to store/retrieve individual items from the variables array and split/join them when requested. This should require a small memory limit as there is no huge unserialize operation going on.

  3. Is this a sustainable solution? Are there any better solution for this problem?

Looking forward to knowing your views!

sites/all/modules/contrib/memcache/memcache.inc

function memcache_is_special_cache_item($cid) {
    $specials = array('variables', 'strongarm');
    return in_array($cid, $specials);
}

function cache_set($cid, $data, $table = 'cache', $expire = CACHE_PERMANENT, $headers = NULL) {
  // Handle database fallback first.
  $bins = variable_get('memcache_bins', array());
  if (!is_null($table) && isset($bins[$table]) && $bins[$table] == 'database') {
    return _cache_set($cid, $data, $table, $expire, $headers);
  }

  // In case of special cache items, we keep the individual items as
  // separate cache items. Later in the retrieval time, we join them
  // together.
  if (memcache_is_special_cache_item($cid)) {

    $keys = array_keys($data);
    foreach ($keys as $key) {
      cache_set($cid . '_' . $key, $data[$key]);
    }

    cache_set($cid . '_keys', $keys);
    return true;

  }

  // remaining part of the function
}

function cache_get($cid, $table = 'cache') {
  // Handle excluded bins first.
  $bins = variable_get('memcache_bins', array());
  if (!is_null($table) && isset($bins[$table]) && $bins[$table] == 'database') {
    return _cache_get($cid, $table);
  }

  // The special cache item was previously saved as individual items,
  // so now we have to retrieve them separately and join them together
  // and send as one item.
  if (memcache_is_special_cache_item($cid)) {

    $keys = cache_get($cid . '_keys');
    if (is_null($keys->data)) {
      return false;
    }

    $data = array();
    foreach ($keys->data as $key) {
      $data[$key] = cache_get($cid . '_' . $key);
    }

    return $data;
  }

  // remaining part of the function
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.