Speeding up Magento: the burden of Two Level cache

The generic approach to solving Magento speed problems is well known: cache, cache, cache. But while debugging a standard Magento installation, I’ve discovered some peculiar behaviour: some type of caching will actually slow down your site.

The problem occurs when you have configured a RAM based block cache, such as memcache or APC (you should, because this type is a magnitude faster than the standard disk or database caches!). You might have noticed, that even though you are using RAM, Magento will still write files to its var/cache/ folder. The reason for this is that Magento automatically engages the Two Level caching mechanism (Zend reference manual). Magento will write only parts of the cache fragments to the fast cache (APC) and write everything to the slow cache (default: file storage).

This is a good strategy if your fast cache has a limited amount of RAM. But since memory is very cheap nowadays, chances are that you can fit your whole shop many times in the fast cache and you would never have to rely on the slow cache. And writing to the slow cache only wastes unnecessary CPU cycles.

I found out by stracing the Magento server process and adding some debug output to the various cache handlers. Without slow_backend defined, you will get this:

Unfortunately, there is no configuration option to disable the Two Level caching mechanism. You could modify the code, in which case you should edit app/code/core/Mage/Core/Model/Cache.php and set  $enable2levels to false somewhere around line 158.

Luckily there’s an easier approach as well. An undocumented feature exist, called “slow_backend_store_data”. You can find its syntax in local.xml.additional and you should set it to “0”. As its name implies, it prevents the 2nd level cache from writing (effectively disabling the 2nd level cache).

But! This only works if you have set slow_backend to “database” (see line 254 of app/code/core/Mage/Core/Model/Cache.php). What is the logic of this? I don’t know. But it means that if you did not define slow_backend in the configuration, it will default to File and hence the slow_backend_store_data setting will be ignored.

To summarize: Two Level cache incurs unnecessary overhead if your primary RAM cache is large enough. You can disable it by pointing your slow backend to the database and disabling slow data store.

Here’s the relevant part from my local.xml config:

Note: if you’re hosted with Byte, you should substitute Apc with memcached.

More info on Two Level Cache and its problems can be found in this excellent post by Fabrizio