What is Opcode and why cache it?
As you know, PHP is an interpreted language, and every instruction in your code has to be compiled into intermediate language before being passed over to the web server for execution. This intermediate language is known as Opcode. To see a dump of Opcode generated for your script you can use VLD extension developed by Derick Rethans and available at http://pecl.php.net/package/vld. A sample opcode output for a “Hello World” script would be like this:
<?php echo “Hello”.” “.”World!”; ?>
Output
function name: (null) number of ofs: 5 compiled vars: none line # * op fetch ext return operands ---------------------------------------------------------------------------------------- 2 0 > EXT_STMT 1 CONCAT ~0 'Hello', '+' 2 CONCAT ~1 ~0m 'World%21' 3 ECHO ~1 3 4 > RETURN 1 branch: # 0; line: 2- 3; sop: 0; eop: 4
Similarly every line in your code is compiled down every time your server works on a request. Depending on complexity of your application (and Magento, as we know, is quite complex) this process can take rather long, especially when under heavy load. So why not storing processed opcodes in some sort of a cache and return them when necessary instead of going through the entire routine? This what PHP life cycle looks like with and without opcode caching [1]:
With opcode caching enabled the system makes a check if the requested PHP code had already been compiled into opcode. When none found the system parses and compiles your script into opcode and saves it into the cache for later. When the same script is requested again, the cached opcode is returned thus sparing the need to repeat the process.
There are several opcode caching solutions available. Five of them (APC, Zend Optimizer, XCache, ionCude Encoder and eAccelerator) are compared here http://itst.net/654-php-on-fire-three-opcode-caches-compared . I am going to review APC and its impact on performance of a Magento shop.
Testing APC Opcode Caching
APC (stands for Alternative PHP Cache) is available here http://pecl.php.net/package/APC . On a Unix machine with PECL installed you can get APC by running the command sudo pecl install apc. Once the automated setup is done you must complete the installation by editing the php.ini file. The minimal required settings are as follows:
extension=apc.so apc.stat=1 apc.enabled=1
The last line takes value 1 or 0 to enable or disable the opcode caching.
For our test I have set up a standard Magento community (v. 1.6.2.0) installation with sample data. I will run benchmarks on its front page and a product page. As benchmarking tool I am going to use ab – Apache HTTP Server benchmarking tool.
Please note that the benchmarking results can be different when performed on another machine with different hardware and software configuration. The purpose of this test is not to get average Magento response times but to compare its performance on a server with and without APC caching. After running 5 tests I get the following average results.
APC disabled
Front page, test command:
~$ sudo ab -n 1000 -c 5 http://myserver/
Frontpage (APC disabled), 1000 request, concurrency 5.
Stage | Min (ms) | Mean (ms) | [+/-] sd | Median (ms) | Max (ms) |
Connect | 0 | 0 | 0 | 0 | 0 |
Processing | 202 | 1131 | 1166.3 | 662 | 11794 |
Waiting | 184 | 868 | 829 | 583 | 10190 |
Total | 202 | 1131 | 1166.3 | 662 | 11794 |
The mean number of requests per second was 4.42. Time to process 1000 requests: 226.378 seconds.
Product page, test command:
~$ sudo ab -n 1000 -c 5 http://myserver/sony-vaio-vgn-txn27n-b-11-1-notebook-pc.html
Product page (APC disabled), 1000 request, concurrency 5.
Stage | Min (ms) | Mean (ms) | [+/-] sd | Median (ms) | Max (ms) |
Connect | 0 | 5 | 70 | 0 | 1536 |
Processing | 372 | 1936 | 1430.9 | 1352 | 12200 |
Waiting | 96 | 1633 | 1182.1 | 1184 | 10604 |
Total | 372 | 1936 | 1433.8 | 1361 | 12201 |
The mean number of requests per second was 2.57. Time taken to process 1000 requests: 388.871 seconds.
It is no surprise that processing of the front page takes less time than that of a product page since most of the front page content is static.
APC enabled
Now I will enable the APC and run the tests again
Front page, test command:
~$ sudo ab -n 1000 -c 5 http://myserver/
Front page (APC enabled), 1000 request, concurrency 5.
Stage | Min (ms) | Mean (ms) | [+/-] sd | Median (ms) | Max (ms) |
Connect | 0 | 2 | 30.5 | 0 | 688 |
Processing | 111 | 575 | 537.8 | 348 | 4971 |
Waiting | 32 | 448 | 378.1 | 317 | 2821 |
Total | 111 | 576 | 538.2 | 349 | 4971 |
% to w/o caching | 55% | 51% | 53% | 42% |
The mean number of requests per second was 8.65 (96% improvement!). Time to process 1000 requests: 115.663 seconds (49% less).
Product page, test command:
~$ sudo ab -n 1000 -c 5 http://myserver/sony-vaio-vgn-txn27n-b-11-1-notebook-pc.html
Product page (APC enabled), 1000 request, concurrency 5.
Stage | Min (ms) | Mean (ms) | [+/-] sd | Median (ms) | Max (ms) |
Connect | 0 | 4 | 46.3 | 0 | 843 |
Processing | 232 | 1216 | 912.4 | 872 | 7396 |
Waiting | 35 | 1052 | 796.6 | 754 | 7316 |
Total | 232 | 1220 | 922.8 | 875 | 8239 |
% to w/o caching | 62% | 63% | 64% | 68% |
The mean number of requests per second was 4.09 (59% improvement). Time taken to process 1000 requests: 244.296 seconds (37% less then without caching).
To sum up
So with APC caching enabled the results show much improvement. Now the processing of the front page is nearly twice as fast and the server is capable to process twice as many requests per second as compared to with caching disabled. The improvement of the product page performance is also substantial. The processing takes only 62% to 68% of time it takes without caching, and 59% more requests are processed per second than before.
To visualize the APC caching impact on a Magento store let’s use the APC management tool that becomes available once the APC is installed. A file called apc.php can be found under /usr/share/php/apc.php. Copy this file into your web server directory so that it can be called by its URL in a browser.
Below a screen shot from this tool shows, that after our tests the APC has cached all the php scripts participating in the requests: 491 of them! Now imagine, that for every Magento shop request several hundred php files must be read, parsed and processed before returning the output and you will realize, how important opcode caching is.
Sources:
[1] Padilla, A, Hawkins, T, Pro PHP Application Performance: Tuning PHP Web Projects for Maximum Performance, Apress 2010
Thank you Oleg,
The best is, it also works in development.