by James Sansbury

Module Monday: Entity Cache

Most of us are well aware about Drupal's latest foray into abstract nouns: Entities. An entity is any sort of content on your site, be it a node, user, comment, etc. If you're noticing that loading up nodes, users or comments has become a bottleneck on your site, thanks to the Entity Cache module, scaling this burden out to a separate caching layer can be as simple as a click of a button. The Entity Cache module stores the fully loaded object into cache using Drupal's cache API. This means that when that object is requested again, it can grab the whole object out of that cache, bypassing expensive SQL queries and other resource intensive tasks.

This module is lean and mean and needs no administration interface, so to showcase it, I set up a Drupal site and ran some quick benchmarks against it. To start, I installed a fresh Drupal 7 site and generated 1000 users using the Devel Generate module that comes packaged with Devel. I then wrote and enabled a quick custom module that mimics what you might see if your site executes some expensive operations when a user is loaded. I also created this simple Drush script to load up each of those 1000 users and then display the total number of seconds or milliseconds it took to process:


$start = microtime(TRUE);

for ($i = 1; $i <= 1000; $i++) {
  if (user_load($i)) {
    $loaded++;
  }
}

$duration = microtime(TRUE) - $start;
// If it's less than 1 second, display in milliseconds.
if ($duration < 1) {
  $time        = ceil($duration * 1000);
  $granularity = 'milliseconds';
}
// Otherwise, use seconds.
else {
  $time        = ceil($duration);
  $granularity = 'seconds';
}

$dt_args = array(
  '!count'       => $loaded,
  '!time'        => $time,
  '@granularity' => $granularity,
);
drush_log(dt('!count users were loaded in !time @granularity.', $dt_args), 'ok');
  

So let's go try this script out and see how long it takes.


$ drush scr entitycachetest.php
1000 users were loaded in 39 seconds.                     [ok]
  

Drupal comes with it's own caching layers, so let's run that script a few more times to see how long it takes with those caches filled up.


$ drush scr entitycachetest.php
1000 users were loaded in 16 seconds.                     [ok]
$ drush scr entitycachetest.php
1000 users were loaded in 16 seconds.                     [ok]
  

Ok, so it looks like it's now executing in about 16 seconds pretty consistently. Now let's download and enable the Entity Cache module and compare.


$ drush dl entitycache
Project entitycache (7.x-1.1) downloaded to               [success]
drupal7/sites/all/modules/contrib/entitycache.

$ drush en entitycache -y
The following extensions will be enabled: entitycache
Do you really want to continue? (y/n): y
entitycache was enabled successfully.                     [ok]
  

Ok, we've downloaded and enabled Entity Cache module, so let's fire off our script once more.


$ drush scr entitycachetest.php
1000 users were loaded in 43 seconds.                     [ok]
  

Hmm, so at first it would appear that our performance actually degrades. Keep in mind, these caches need to get filled up first, so let's run it again and see what kind of performance we get.


$ drush scr entitycachetest.php
1000 users were loaded in 558 milliseconds.               [ok]
  

Whoa! Talk about a performance increase! We went from taking 16 seconds to load 1000 users to less than 1 second. We paid for it a bit in the beginning, as it took an additional 4 seconds the first time the script was run, but I think it was worth it!

One thing to note here is that I'm not using Memcache or any other caching plugin, so the Entity Cache module will be storing all this stuff in MySQL. This means if you are using Memcache, you'll probably see even better results.

At the time of this writing Entity Cache module has support for node, comment, taxonomy term, taxonomy vocabulary, file and user entities. There is currently no support for non-core entities, however it is possible to write your own integration. It has a stable release for Drupal 7, but will not be back ported for Drupal 6. If you are looking for similar solutions for Drupal 6, the maintainer suggests looking to this Pressflow merge request or the Advanced cache module.

If your Drupal 7 site is slow, lots of things can contribute to that, so I urge you not to just download and enable every module that boasts performance benefits. It's best to isolate the bottleneck first, and then find solutions tailored for that bottleneck. That said, if you find that loading of certain entities is that bottleneck, this module is a quick win to not only make your site more performant, but also be able to scale the amount of traffic your site can receive by redirecting database traffic to Memcache instead.

newsletter-bot