Since writing Using PHP APC with Cherokee I noticed that my cache hits were dropping and my cache misses were growing. This is my first attempt at tweaking the configuration of
php-apc to try to eke out more performance.
I enabled my
apc.php page (check the previous article), checked the statistics, and saw that the
Cache full count was growing. My cache had filled several times.
According to the APC configuration documentation there are two settings that control the expiration of cache entries. They are:
By default, they are set to
According to the documentation:
In the event of a cache running out of available memory, the cache will be completely expunged if ttl is equal to 0. Otherwise, if the ttl is greater than 0, APC will attempt to remove expired entries.
Essentially, that meant my cache was completely expunged every time it filled and a new entry needed to be cached. Clearing the entire cache in order to store one more entry strikes me as less than optimal!
I'm surprised APC doesn't offer any smarts for managing a full or near-full cache (eg, using algorithms such as Least Recently Used or Second Chance Replacement to choose an entry to replace). The only option appears to be adjusting the cache expiry (
apc.user_ttl) or the size of the cache (
At this stage I didn't think it was a good idea to increase the memory used by
php-apc. I'm on a Linode 512, a memory-constrained VPS. Also, by expiring infrequently-requested cache entries I might find that I can use less memory for the cache instead of more.
So I added the following to
# Does exactly what you think it does... apc.enabled=1 # Number of seconds (7200 == 2h) before cache # entries are expired. Otherwise, the default (0) # means that the entire cache will be expunged # if/when the cache fills. apc.ttl = 7200 apc.user_ttl = 7200
Of course, after making the changes there's still more to be done. I'm using Cherokee and FastCGI, so I need to restart the
php-cgi processes for the change to take effect. I've found that
/etc/init.d/cherokee restart doesn't take care of restarting the
php-cgi processes. Nor does using the
Graceful restart or
Hard restart options in
cherokee-admin. Instead, I believe (again, please correct me if I'm wrong) that sending the
php- cgi means that the
php-cgi processes will terminate when they have finished handling their current requests.
killall -TERM php-cgi service cherokee start
After these changes:
if I find there is too much free memory in the cache and the cache misses are too high, I will increase the expiry times
if I find there is too much free memory but the cache hits are high (say, over 75%), I will probably decrease the size of the cache
if everything is just right, I'll leave things as they are
We'll find out in round 2...
In the meantime, follow me on Twitter. It's free. Cheers!