making bbPress (and WordPress) work better!

Even faster APC PHP cache by turning off file stat

I’ve recently had to abandon using eaccelerator because they are just not keeping up anymore with PHP releases and they even removed variable data cache support just to get PHP 5.3 compatibility. It’s sad because they were the fastest and most stable for years.

So I have been testing xcache and APC instead.

One trick I use on large/active servers for an additional performance boost is to turn off the file stat feature on the PHP opcode cache. This makes it stop checking the timestamp on each and every PHP file executed. WordPress for example has over 100 php files totaling nearly 3 megabytes on a typical install.

You’d use ONE of these directives in php.ini depending which opcode cache you use:


apc.stat = 0
xcache.stat = "Off"
eaccelerator.check_mtime="0"

Of course this is only practical in an environment where you are the only user on the whole server and rarely update existing files, because they will then no longer update in the cache. You could never do this on a shared server.

Now, when it comes time for you to update a few files, this is where it gets tricky, because it’s very inefficient to delete 1000+ files out of the opcode cache, as they would all have to be rebuilt.

eAccelerator had a very useful button in it’s control panel to only delete “expired” files in the cache, where even though file stat (file modification time) checking was turned off, you could do it “on demand” by clicking the button. So replace the file(s) and then click the button, and instead of purging the entire cache of say 1000 files, it would only delete the few you changed.

xcache and APC do not have any such button. Your only option is to purge the entire cache, which is incredibly wasteful.

I tried to write a similar function for xcache but I ran into a problem where their API is just not robust enough to accomplish this, it does not allow individual files to be purged. They also do not save the initial filemtime if stat is turned off in the first place. I am awaiting feedback here to see if I am wrong.

But APC is very robust and not only stores mtime but also can delete individual files. So I give you the equal of “delete expired” (aka “delete newly uploaded/replaced”). Maybe it should be a button in their control panel too.

<?php
if (!function_exists('apc_cache_info')) { die('APC is not installed/running');}
$data = apc_cache_info(); $expired=array();
if (empty($data['cache_list'])) { die('no cached files');}

foreach ($data['cache_list'] as $file) {
	if (!empty($file['mtime']) && !empty($file['filename']) 
		&& (!file_exists($file['filename']) || (int)$file['mtime']<filemtime($file['filename']))) {$expired[]=$file['filename'];}
}
if (!empty($expired)) {apc_delete_file($expired);} 
echo count($expired),' deleted';

4 responses

  1. bind727

    Nice work! I am going to give this a try. +1 to include that in apc.php

    May 4, 2012 at 10:36 pm

  2. Brilliant! I’m now using this on our stack so we can take advantage of apc.stat=0, curling the script every minute in case of any changes globally.

    Cheers!

    July 17, 2012 at 5:13 pm

  3. thanks a lot, it was really inspirational. I removed xcache and replace with APC, and I would suggest to everyone doing that…my site is highly loaded – handling around 10.000 users online.

    November 9, 2012 at 1:11 pm

  4. use xcache control panel “delete expired”

    October 15, 2014 at 11:14 am

Leave a comment