Monday, July 23, 2012

Everything you need to know about APC (Alternate PHP cache)

http://linuxaria.com/howto/everything-you-need-to-know-about-apc-alternate-php-cache?lang=en


If you are a system administrator and you want to push the performance of your PHP website such as Drupal, WordPress or wrote by you or other programmers, there are good chances that you’ve heard about the Alternate PHP Cache or simply APC.

    The Alternative PHP Cache (APC) is a free and open opcode cache for PHP. Its goal is to provide a free, open, and robust framework for caching and optimizing PHP intermediate code.

That everything you’ll read about APC on the php.net site, and i think is not enough in comparison to the huge boost of performance that this small component can give you, for some quick facts check the tests done by Guillermo Garron on his website.



How APC works

The first thing you need to know, is how a PHP program is run by the Zend Engine, these are steps to go from your PHP script to the code really used by the Engine, this is commonly known as “opcodes”, representing the function of the code.

    The first step is reading the PHP code from the filesystem and put it into memory.
    Lexing : The php code inside is converted into tokens or Lexicons.
    Parsing : During this stage, tokens are processed to derive at meaningful expressions.
    Compiling : The derived expressions are compiled into opcodes.
    Executing : Opcodes are executed to get the final result.

The goal of APC is bypass the steps from 1 to 4, caching in a shared memory segment the opcodes generated and then copies them into the execution process so Zend can actually execute the opcodes.

From lampzone.wordpress.com

    Here are the detailed steps of what APC really does

    1. During module init time ( MINIT), APC uses mmap to map file into shared memory.

    2. During request time, APC replaces zend_compile_file() with its own my_compile_file().

    What does my_compile_file do ?

    1. If APC couldn’t find file in the cache, APC will call zend_compile_file to compile file

    2. Get returned opcodes and store them into shared memory which read/write from different Apache child processes. ( We are talking about Apache prefork MPM here.)

    3. Also store classes and function tables in shared memory.

    4. Copy opcodes into Apache child process memory so Zend can execute the code.

So this is the theory, let’s see now how to install and configure it
APC installation

APC is a PHP extension so you have 2 ways to install it :

1) Install APC from a repository of your distribution.
I suggest to use this way whenever possible, keeping everything you have on your computer/server installed from a repository is a good practice that i always try to follow.

On Debian and Ubuntu APC is available on the main repository with this name:

root@xubuntu-home:~# apt-cache search apc php
php-apc - APC (Alternative PHP Cache) module for PHP 5

So you can install it with the command

sudo aptitude install php-apc

While if you use Red Hat Enterprise, Centos or Fedora you can use this command :

sudo yum install php-pecl-apc

2) The second way to install APC is with PECL, with this method you’ll download the last source and compile it for you computer.

On Debian and Ubuntu this should work (the name of the packages can change depending on your version of Ubuntu/Debian)

$ sudo apt-get install php-pear php5-dev apache2-threaded-dev build-essential
$ sudo pecl install apc

As told i suggest the method number 1, in the second you could have problem during the compilation and over time some updates could broke your local installation of APC.

APC Configuration

Once installed APC must be enabled in the configuration file of PHP: php.ini, if you have installed APC from a package this is already done and you just have to restart Apache (or FastCGI daemon like FPM) to see a new APC section in phpinfo() which will confirm it’s enabled.

Otherwise you have to include in your php.ini this line:

extension=apc.so

This is enough to have APC installed with all default parameters, but probably you want to change some of the default values.
Among the parameters there is apc.shm_size, which specifies how much memory to use for APC, the default is 30 MB, depending on your application and RAM on the server raise this number to 64, 128 or even 512 MB.

This is a suggested configuration for a box with 1Gb of RAM:

# cat /etc/php5/conf.d/apc.ini
extension=apc.so
apc.enabled=1
apc.shm_size=128
apc.cache_by_default="1"
apc.shm_segments="1"
apc.ttl="7200"
apc.user_ttl="7200"
apc.gc_ttl="1800"
apc.optimization = 0
apc.num_files_hint="1024"
apc.use_request_time = 1
apc.mmap_file_mask="/tmp/apc.XXXXXX"
apc.enable_cli="0"
apc.slam_defense="0"
apc.file_update_protection="2"
apc.max_file_size="1M"
apc.stat="1"
apc.write_lock="1"
apc.report_autofilter="0"
apc.include_once_override="0"
apc.rfc1867="0"
apc.rfc1867_prefix="upload_"
apc.rfc1867_name="APC_UPLOAD_PROGRESS"
apc.rfc1867_freq="0"
apc.localcache="0"
apc.localcache.size="512"
apc.coredump_unmap="0"

For a full explanation of these settings, refer to the online documentation.

APC includes a web page where you can see the usage of the cache, including fragmentation and other useful information. Copy the file apc.php (located in /usr/share/doc/php-apc/apc.php for Debian and Ubuntu) to your document root and point your browser to it to see a screen like this one:

apc.php

From here you can see the hits/misses % and an important statistic: Cache full count, this number tell how many time the cache has been completely filled, if this number goes up too quickly you probably have to raise the size of the cache.

One word of warning: If you don’t periodically restart Apache or PHP-FPM, your cache could become fragmented, as you’ll be able to see by visiting that web page. To avoid this, periodically empty the cache. I use a cron setting that once a day calls a web page on my site, which I call apc-clear.php, that empties the cache. It also checks that the address invoking it is local so it cannot be called from outside. Here is the content of apc-clear.php:


if (in_array(@$_SERVER['REMOTE_ADDR'], array('127.0.0.1', '::1')))
{
  apc_clear_cache();
  apc_clear_cache('user');
  apc_clear_cache('opcode');
  echo json_encode(array('success' => true));
}
else
{
  die('SUPER TOP SECRET');
}

And this is my cron:

0 6 * * * /usr/bin/curl --silent http://myserver.com/subdir/apc-clear.php

Conclusions

As you have seen in this article, setting up APC is really easy and will improves the throughput of your php pages many times, so why you should not use it ?

No comments:

Post a Comment