Testdriving Zend Optimizer+

Last Tuesday, Zend Optimizer+ was released as open source software and I couldn't resist taking it for a spin. This piece of software is a serious candidate to be integrated in the PHP core and is an alternative to APC, another opcode cache solution. Which makes it very interesting for all PHP developers. Let's see what Zend Optimizer+ actually is and how it can be installed.

Opcode caching

PHP is an interpreted language. This means that every time a web page is requested, the server has to compile all the PHP files needed to generate it from source to a binary format that the machine understands. Needless to say, this is slow. There are many PHP accelerators on the market that are basically extensions, designed to improve the performance of software applications.

Most of them solve the compilation problem by caching the binary format (also known as bytecodes or opcodes) of the PHP scripts in a shared memory location, from where it can be executed directly. This substantially increases the speed of PHP applications. If your code does not yet use an opcode cache, it is advised to start using one right now.

At the time of this writing, one of the most widely used opcode caches for PHP is the Alternative PHP Cache (APC). This cache does not limit itself to opcode caching, but it also provides a user cache. This user cache is basically a key-value store that uses a configurable amount of memory. APC also has a nice GUI that looks something like this:


Some time ago, APC was even so popular that all the major PHP developers decided to officially endorse APC and had it scheduled for inclusion in the PHP core no later than PHP 6. A lot has happened since, PHP 6 did not happen yet and APC is still not in core.

Another PHP accelerator is Zend Optimizer+. It also improves PHP performance by storing precompiled script bytecode in the shared memory. This eliminates the stages of reading code from the disk and compiling it on future access. In addition, it applies a few bytecode optimization patterns that make code execution faster.

Open source

Last month, PHP developer and co-founder of Zend Technologies Zeev Suraski announced that Zend was looking into open-sourcing Zend Optimizer+ and including it into PHP 5.5. Yesterday, Optimizer+ was effectively released as open source software at


Zeev also opened a PHP request for comments (RFC) at to integrate Optimizer+ into the PHP distribution. This means that the next version of PHP may have Optimizer+ built-in as an opcode cache, which suddenly makes it a very interesting piece of software for all PHP developers.


I immediately booted one of my Debian development boxes with a recent PHP 5.4 to take it for a spin. The first thing you will need to do is remove APC, if you have it installed, because it will interfere with Optimizer+:

apt-get remove php5-apc

Or just disable the module like this:

php5dismod apc

Then, clone the Git repository from GitHub:

git clone git://

This downloads the extension source code on your machine. In order to compile it, you need to have the PHP module development package installed:

apt-get install php5-dev

Change directory into ZendOptimizerPlus, phpize, run the configure script and then compile the extension:

cd ZendOptimizerPlus
./configure --enable-optimizer-plus

The extension will be compiled into the .libs folder. Copy it into your PHP extension library:

cp .libs/ /usr/lib/php5/20100525/

Now you can configure PHP to load the extension. If you would like to tune the extension to match your exact needs, consult the README where all parameters are well documented. You can already configure the extension to use sane defaults, like described in the README on GitHub:

cat << EOF > /etc/php5/mods-available/ZendOptimizerPlus.ini

And run:

php5enmod ZendOptimizerPlus

When you restart your Apache2 server and take a look at phpinfo() output, you will now have the following section:


Optimizer+ does not come with a nice PHP statistics page like APC but you can use the "accelerator_get_status()" function to print memory usage, cache statistics and the list of cached PHP scripts. The function returns an array containing the following elements:

accelerator_enabled - boolean; TRUE if code acceleration is enabled, FALSE otherwise

cache_full -  boolean; TRUE if the Optimizer+ cache is full

memory_usage - array; contains information about Optimizer+ memory usage, with the following keys:
    used_memory - integer; bytes of memory used
    free_memory - integer; bytes of memory available for cache
    wasted_memory - integer; bytes of memory used by invalid or outdated code
    Wasted memory is reclaimed when the accelerator is reset, or when the percentage of wasted memory reaches the value of the max_wasted_percentage directive
    current_wasted_percentage - float; The percentage of wasted opcode cache memory out of total memory available

accelerator_statistics - array; contains current opcode cache usage statistics, with the following keys:
    num_cached_scripts - integer; number of cached scripts
    max_cached_scripts - integer; maximum number of cached scripts
    hits - integer; number of cache "hits" - that are requests for files that had valid cache entries
    last_restart_time - integer; timestamp of the last restart time
    misses - integer; number of cache "misses" - that are requests for files which were not cached
    blacklist_misses - integer; number of requests to blacklisted files
    blacklist_miss_ratio - float; ratio between hits and requests to blacklisted files
    accelerator_hit_rate - float; ratio between opcode cache hits and misses

scripts - array; Each key in the array is the name of an accelerated script. Values are an array with information about the script, with the following keys:
    full_path - string; the full path to the script
    hits - integer; number of cache hits for this script
    memory_consumption - integer; bytes of memory used to cache this script
    last_used - string; string representation of the last time this script was fetched from cache. For example "Thu Jan 31 13:37:40 2008"
    last_used_timestamp - integer; UNIX timestamp of the last time this script was fetched from cache
    timestamp - integer; UNIX timestamp of when the script was cached


Edit: 27/feb/2012: Some frameworks / CMSes were benchmarked by Zeev, you can find the results linked in the RFC. Symfony2 was missing from this list, so I did a benchmark myself with Symfony2.1.8 on Nginx / PHP FPM 5.4.8. Optimizer+ is version 7.0.0-dev, APC is 3.1.13. The Y axis contains the number of requests per second.



The RFC is still under discussion but Zend Optimizer+ is a good candidate to make it into the PHP core.

One of the downsides of Optimizer+ is that it does not have a user cache API like APC. Another important point is that APC uses a memory manager and can reclaim memory associated with a script that is no longer in use. Optimizer+ just marks such memory as dirty, but never actually reclaims it. Optimizer+ restarts itself once the dirty percentage climbs above a configurable threshold.

On the upside, Optimizer+ promotes itself to have a consistent performance edge over APC. Also, it advertises to be fully compatible with PHP releases even before they come out. Lastly, Optimizer+ has optional corruption detection capabilities that can prevent a server-wide crash in case of data corruption.

We'll see how it goes from here. There is still some work to be done and it is unsure if Optimizer+ will even make it into PHP 5.5. Also this is not a one man decision, all the PHP developers will soon vote on the RFC in order for it to be accepted.

Edit 29/mar/2013: In the meanwhile, Zend Optimizer+ was renamed to opcache and did make it into PHP 5.5.