Get your FREE 30 page Developing SOLID Applications guide!

To stat() Or Not To stat()?

Out Of Date Warning

Languages change. Perspectives are different. Ideas move on. This article was published on July 30, 2009 which is more than two years ago. It may be out of date. You should verify that technical information in this article is still current before relying upon it for your own purposes.

The Alternative PHP Cache (APC) is a tool that offers a massive performance gain to almost any PHP application simply by turning it on. This extension to PHP provides both opcode caching and user caching, placing files and data into memory for fast retreival, and, if used correctly, eliminating some of the bottlenecks of the file server or database.

Turning APC on is a great way to get a performance boost, but there are ways to help improve APC’s performance.

The very first thing that APC does when it’s turned on is begin caching the opcode output from all of your PHP files. Essentially, it takes the compiler’s output, stores it in memory, and then retrieves it later on if that file is needed. Also by default, APC checks the file on the file system to determine if it has changed since the last time APC cached the opcodes.

When APC does this, it executes a file-system-level stat() call, which in the scheme of the calls performed is expensive. This call basically helps APC determine if it should execute the opcodes that you have stored in memory, or if it should read and compile the file. This behavior is on by default but can be disabled.

To disable it, you must add the following line to your php.ini file:

apc.stat=FALSE

This will not prevent APC from caching the file if the file is not yet in memory; it will simply keep APC from checking for an updated file each and every time it executes it.

There are some obvious benefits to this. First, you get a performance boost. This method is used by Facebook to improve the performance of its servers. Clearly your production systems are not updated on an exceptionally regular basis, meaning that you don’t have to worry about the files becoming stale in memory.

As with all things, there are also some drawbacks. First, a restart of the webserver or a call of apc_cache_clear() is required before the APC cache will be cleared and any changes will be reflected. This means that you may want to run APC with apc.write_lock in your INI file to keep your servers from crashing. Also, this will not improve poorly written or poorly executed code; bad code will still run slowly, no matter how many boosts you give it. This will only help well-written code run faster. APC is also only effective if the memory is not completely full, so running APC on heavily-visited sites with relatively little memory won’t earn you much of a boost at all. Finally, if you implement this on a low-traffic website you’re unlikely to see any improvement at all; the higher the traffic, the more this will benefit the web server.

As with all things that promise performance improvements, you are encouraged to profile your code and benchmark the improvement before deploying to a production environment.

Warning: Do not run this in a development environment; otherwise you will be unable to see your changes reflected! This is a production feature only.

Write better object oriented PHP today.

Object oriented programming always leaves you with a headache. What if you could master it instead?

Get the book now! »

Brent (@ambirex) wrote at 7/30/2009 6:47 pm:

Here is a crazy idea, you could use incron ( http://inotify.aiken.cz/?section=incron&page=about&lang=en ) to monitor files and call apc_cache_clear() when a file is changed.

Brandon Savage (@brandonsavage) wrote at 7/30/2009 8:12 pm:

That’s one option, though I don’t know that I’d care that much. I can just run “apachectl graceful” every time I update the files, or automate that process in some way when rsync runs.

Oscar (@omerida) wrote at 7/31/2009 1:49 pm:

I’ve noticed that APC and other opcode caches can help with memory, since retrieving the opcodes from the cache require less memory than parsing the PHP file each time. The first time a PHP file is parsed, the scripts memory consumption will be high, but subsequent calls are smaller.

Depending on how memory starved your server is, this can help some as it keeps the memory usage for apache lower, especially if you use prefork.

Do you have any benchmarks for how much turning stat() off can help?