A collection of my thoughts. All expressions are that of mine @wilr and not my employers.

Caching Memory Intensive Tasks in SilverStripe

While working on Facebook Connect integration with SilverStripe I noticed (well actually Sam noticed) that performance was terrible. I was seeing pages take ~5 secs to load. So I set about trying to improve performance.

When ever you are trying to fix performance the first thing you should do it profile, profile and profile more. For me I used the XDebug profiler and determined that 98% of the load time was on this 1 api call. $this->facebook->api(‘me/’); 

That call authenticates the current user and returns all the information we have access about them, so its a pretty vital call! But do you really need to look at up every. single. time? Unlikely. So I implemented a simple cache for caching the results.

Setting up a cache is easy now in 2.4.

$cache = SS_Cache::factory('cache name');
if(!($result = unserialize($cache->load('var name')))) {
	$result = $this->SomeMemoryIntensiveTask();
	$cache->save(serialize($result), 'var name');
return $result;

Stepping through that code

  • We get the current cache that we have called ‘cache name’. You can call ‘cache name’ anything you wish.
  • Looks up the $cache for a record named ‘var name’ again var name can be anything you wish.
  • If var name does not exist in the cache, do the operation and save it back into the cache under the name ‘var name’. This means next time you call that method it will come off the cache (eg If using memcached then straight out of memory which equals fast). 

By caching the initial me/ call the page load times dropped from 3200ms on average to 92ms on average. Easy win.

Final note on caching If you haven’t already make sure that you have installed at least 1 type of caching backend, SilverStripe will love you for it. APC is easy to install and usually you won’t have to edit any config settings to enable it.