PHP is an interpreted language. This means that each time a PHP generated page is requested, the server must read in the various files needed and "compile" them into something the machine can understand (opcode). A typical Drupal page requires more than a dozen of these bits of code be compiled.
Opcode cache mechanisms preserve this generated code in cache so that it need only be generated a single time to server hundreds or millions of subsequent requests.
Enabling opcode cache will reduce the time it takes to generate a page by up to 90%.
PHP is known for its blazing speed. Why would you want to speed up your PHP applications even more? Well, first and foremost is the coolness factor. Next, you'll increase the capacity of your current server(s) many times over, thereby postponing the inevitable need to add new hardware as your site's popularity explodes. Lastly, high bandwidth, low latency visitors to your site who are currently seeing page load times in the 1-2 second range will be shocked to find your vamped up site serving up pages almost instantaneously. After enabling opcode cache on my own server, I saw page loads drop from about 1.5 seconds to as low as 300ms. Now that's good fun the whole family can enjoy.
Opcode Cache Solutions
There are a number of opcode caching solutions. For a rundown on some of them, read this article. After a bit of research and a lot of asking around, I concluded that Eaccelerator was the best choice for me. It's compatible with PHP5, is arguably the most popular of its kind, and is successfully used on sites getting far more traffic than you or I are ever likely to see.
This is the fun and exciting part. Implementing opcode cache is far easier than you might imagine. The only thing you'll need is admin (root) access to your server. If you're in a shared hosting environment, ask your service provider about implementing this feature if it is not in place already. These instructions apply to *nix environments only.
Poor Man's Benchmarking
If you would like to have some before and after numbers to show off to your friends, now is the time to get the 'before' numbers. Ideally, you will have access to a second host on the same local network as your server so that the running of the test does not affect the results. For those of us without such access, we'll just have to run the test on the actual webserver, so don't submit these results in your next whitepaper:
Apache comes with a handy benchmarking tool called "ab". This is what I use for quick and dirty testing. From the command line, simply type in the following:
ab -n 1000 -c 10 http://[YOURSITE.COM]/
Here is a portion of the results I got on my own test:
Concurrency Level: 10 Time taken for tests: 78.976666 seconds Complete requests: 1000 Failed requests: 0 Write errors: 0 Total transferred: 13269256 bytes HTML transferred: 12911899 bytes Requests per second: 12.66 [#/sec] (mean) Time per request: 789.767 [ms] (mean) Time per request: 78.977 [ms] (mean, across all concurrent requests) Transfer rate: 164.07 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 7 51.3 0 617 Processing: 77 725 1704.4 300 21390 Waiting: 0 673 1697.5 266 21383 Total: 77 732 1706.2 307 21390 Percentage of the requests served within a certain time (ms) 50% 307 66% 468 75% 625 80% 639 90% 805 95% 3808 98% 6876 99% 8529 100% 21390 (longest request)
The single most useful number is 'Requests per second', which in my case was 12.66.
Download, Build and Install
First, download the source code.
Get it to your server and do the following (I'm assuming you have gcc on your system, if not, get it):
tar jxvf eaccelerator-0.9.5.tar.bz2 cd eaccelerator-0.9.5 phpize ./configure make make install
Configure Apache and Restart
If you have an /etc/php.d directory, create the file /etc/php.d/eaccelerator.ini for your new settings. Alternatively, you can put them in your php.ini file. Your configuration should look something like this:
zend_extension="/usr/lib/php/modules/eaccelerator.so" eaccelerator.shm_size="32" eaccelerator.cache_dir="/var/cache/eaccelerator" eaccelerator.enable="1" eaccelerator.optimizer="1" eaccelerator.check_mtime="1" eaccelerator.debug="0" eaccelerator.filter="" eaccelerator.shm_max="0" eaccelerator.shm_ttl="0" eaccelerator.shm_prune_period="0" eaccelerator.shm_only="0" eaccelerator.compress="1" eaccelerator.compress_level="9" eaccelerator.log_file = "/var/log/httpd/eaccelerator_log" ; eaccelerator.allowed_admin_path = "/var/www/html/control.php"
Adjust values according to your particular distribution. For more details on configuring eaccelerator, see the settings documentation.
See Eaccelerator in Action
The value eaccelerator.allowed_admin_path, if enabled, should point to a web accessible directory with a copy of 'control.php' (which comes with the eaccelerator source code). Edit this script, changing the username and password. You can then access this control panel and see exactly what eaccelerator is caching
See the results
After enabling Eaccelerator on devbee.com, I ran my benchmark again, and here are the results:
Concurrency Level: 10 Time taken for tests: 10.472143 seconds Complete requests: 1000 Failed requests: 0 Write errors: 0 Total transferred: 13129000 bytes HTML transferred: 12773000 bytes Requests per second: 95.49 [#/sec] (mean) Time per request: 104.721 [ms] (mean) Time per request: 10.472 [ms] (mean, across all concurrent requests) Transfer rate: 1224.30 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 0 0.1 0 4 Processing: 20 103 52.1 96 345 Waiting: 17 92 50.1 83 342 Total: 20 103 52.1 96 345 Percentage of the requests served within a certain time (ms) 50% 96 66% 122 75% 137 80% 147 90% 176 95% 201 98% 225 99% 248 100% 345 (longest request)
We are now serving up 95.49 requests per second. That's 754% increase in server capacity. Had I been able to run the tests from another machine on the same network, I believe the numbers would be even more dramatic.