Boost PHP Performance on OS X by Installing APC

Photo of Greg
Photo by NASA - http://flic.kr/p/czoDK5

Possibly the single biggest boost to PHP performance comes from caching bytecode in RAM and reusing it, rather than recompiling it from scratch each time a particular piece of code runs. Installing APC is one of the easiest ways to make it happen.

Caching PHP bytecode in RAM offers one of the most straightforward ways of improving the back end component of page performance — i.e., the time spent by your server responding to requests. If you’ll be using PHP at all on your server, it’s worth installing an opcode cache such as APC.

(Other options are available, including XCache, and a distributed memory caching system like memcached can boost performance even further. But for basic use, where you’re looking for the most benefit for a given level of effort, coupled with the least hassle and overheads in terms of maintenance, I think APC is hard to beat. Configured correctly, it can be entirely “set it and forget it”.)

To begin, you’ll first need PCRE. You can download the latest version directly at the PCRE site (version 8.33 as of this October 2013 update to the original post) and expand and install as follows:

tar xvf pcre-8.33.tar.gz

cd pcre-8.33

./configure

make

sudo make install

After that, installing APC is a breeze (assuming you already have autoconf and have pear up and running as per the separate article on enabling WordPress to work with SSH2):

sudo pecl install apc

Unless you know otherwise for your context, it’s best to accept the default answer to each question you’ll be asked during the installation.

As indicated at the end of the installation, you’ll need to add the following line to your php.ini file, which lives at /private/etc:

extension=apc.so

And restart Apache:

sudo apachectl graceful

A file called apc.php will also be left in your /pear directory, which you can copy to your default site (if it’s password protected as suggested in my earlier article on starting up web services) or somewhere else that is safe — don’t provide it somewhere where the whole world can see it! As an extra measure of security, you should rename the file to something other than apc.php. Normally, it’s also recommended to set a username and password within the file itself, but unfortunately the way browsers cache and return usernames and passwords, if you do set a username and password within the file, this will likely conflict with those used for digest authentication. Therefore, it may be preferable to leave the username and password out of the apc.php file itself and stick with server-level digest authentication.

When you visit the (renamed) apc.php in your browser, you’ll see a whole slew of information about the cache, and under ‘Version Check’, you may see a warning that you’re not running the latest version. Note that the version check won’t tell you if the latest version is actually a beta; you’ll need to check that yourself. If the installation didn’t grab the latest version, and you want the latest version, you can find out the latest version number from the URL supplied with the warning and upgrade like so, replacing the version number shown here with whatever is correct at the time:

sudo pecl upgrade apc http://pecl.php.net/get/APC-3.1.13.tgz

(Note that 3.1.13 is a beta.)

If you keep an eye on how the APC cache performs over time, especially occasions when the cache becomes full, you can tweak any necessary parameters listed under ‘Runtime Settings’ by adding appropriate lines to php.ini and restarting Apache.

Two of the most important APC settings are these defaults:

apc.shm_size=32M
apc.stat=1

The former sets the maximum amount of memory to be used for the cache, while the latter sets whether APC should check on disc whether a file has been modified since the last time it was requested. These days, a 32MB cache is much too small, so you may wish to boost it to 128, 256, 512 or perhaps even more if you have a great deal of available memory. And as for checking whether PHP files have changed before relying on the cached version, you’ll pay a bit of a performance penalty by leaving this capability switched on — but on the other hand, if you switch it off, you must remember to clear the cache manually each time you make any changes to PHP code, or expect chaos to reign. Personally, I’d much rather accept the performance penalty.

The following setting places a limit on how large a file may be before it’s cached; it’s possible you may want a slightly higher value than the default:

apc.max_file_size=1M

You might also want to tweak these defaults, which ‘hint’ to APC about the number of distinct source files which will be included or requested, in the case of the former, and the number of distinct user cache variables which might be stored, for the latter:

apc.num_files_hint=1000
apc.user_entries_hint=4096

The configuration manual suggests that the former is primarily useful for sites with thousands of files and recommends setting both to zero or omitting them altogether if you’re not sure of an appropriate value. After running APC for a few hours or days, you’ll probably be able to get a good idea of a suitable num_files_hint just by checking how many files have in fact been cached.

Finally, if it should happen that something goes haywire, and you’d like to reinstall APC with different options at compile time, this is easily done. For example, after upgrading to the 3.1.13 beta, and accepting the default answers during installation — which includes pthread read/write locks, even though they are marked as experimental — I experienced an uncomfortably large number of errors like the following:

PHP Fatal error: include_once(): unable to obtain pthread lock (EDEADLK) in... on line...

To remove pthread read/write locks and restore pthread mutexes, which should have been set as default, I removed APC with this:

sudo pecl uninstall apc

Then it’s a simple matter of repeating the steps from above to install APC and then upgrade it — but this time changing the ‘no’ which is already filled in for pthread mutexes into a ‘yes’ and changing the ‘yes’ which is already filled in for pthread read/write locks into a ‘no’.

All material on this site is carefully reviewed, but its accuracy cannot be guaranteed, and some suggestions offered here might just be silly ideas. For best results, please do your own checking and verifying. This specific article was last reviewed or updated by Greg on .

This site is provided for informational and entertainment purposes only. It is not intended to provide advice of any kind.