Published by Danijel Krmar on November 20th 2013
PHP 5.5 is out and everyone is buzzing about Zend Optimizer+ integration (now called Zend OPcache). With this integration, PHP finally got a built-in opcode cache.
Here's the biggest game changer - as OPcache is included in the PHP core and it will have to be maintained with every new PHP release. There should be no more weird problems caused by incompatibilities between a new PHP release and the opcode cache. Also, the development of APC has slowed down and, at least for now, APC is not compatible with PHP 5.5.
We had to test how OPcache works with activeCollab, since we are the ones preaching about using APC to our customers. The bottom lines is, you can use activeCollab without APC, but seriously, you don't want to. The advantages of using APC can be 50-60% in application execution time and a decrease of 20-30% in system utilization. We also rely on APC for our own SaaS platform.
- PHP < 5.5.x
The installation is straightforward. If you have PHP older than the stable 5.5.x release, you can install Zend OPcache from the pecl archive:
$ pecl install zendopcache
Manual installation is also possible. Download the latest version from http://pecl.php.net/package/ZendOpcache:
1 2 3 4 5 6 7 8
$ cd /usr/src $ wget http://pecl.php.net/get/zendopcache-7.0.2.tgz $ tar xvf zendopcache-7.0.2.tgz $ cd zendopcache-7.0.2 $ phpize $ ./configure $ make $ make install
The last command will install the opcache extension to your modules folder. After installing, add zend_extension=opcache.so or zend_extension=/full/path/to/opcache.so to your php.ini.
- PHP >= 5.5.x
In case you are an early adopter and you already have PHP 5.5.x, you'll get the extension built in. It will be disabled by default, so you have to enable it by adding:
to your php.ini.
We made some changes to the default Zend OPcache configuration by changing the following config options in php.ini. Our opcache configuration now has the following values:
1 2 3 4 5 6 7 8 9 10
[opcache] opcache.enable=1 opcache.enable_cli=1 opcache.memory_consumption=128 opcache.interned_strings_buffer=8 opcache.max_accelerated_files=4000 opcache.max_wasted_percentage=5 opcache.use_cwd=1 opcache.validate_timestamps=0 opcache.fast_shutdown=1
IMPORTANT NOTE Setting opcache.validate_timestamps to 0 (disabling it) will increase the performance, especially when you have an application with a lot of files, but it also means you have to reset the OPcache manually when you alter the application files. If not fully understood, opcache.validate_timestamps=0 can break your application or cause hard to find issues. The configuration above is for benchmarking only. For your production environments please use following values (note the opcache.validate_timestamps=1 part):
1 2 3 4 5 6 7 8 9 10 11
[opcache] opcache.enable=1 opcache.enable_cli=1 opcache.memory_consumption=128 opcache.interned_strings_buffer=8 opcache.max_accelerated_files=4000 opcache.max_wasted_percentage=5 opcache.use_cwd=1 opcache.validate_timestamps=1 opcache.revalidate_freq=1 opcache.fast_shutdown=1
activeCollab relies heavily on file cache, so just throwing opcode into the equation won't do it in the right way. We've done some tests using only PHP 5.5.3 + OPcache and there is a performance gain, but it is only about 10-20%, so we didn't take it into account. If you want to get the most out of activeCollab, you have to use opcode + file caching.
As we successfully use a distributed memcached setup on our ManageProjects.com (activeCollab in the Cloud) platform, the decision about a file caching mechanism was easy. For our test environment, we will use memcached as a file cache server.
We use solely Debian in our environment, which has memcached in its repository. We've installed memcached and the memcached PHP extension using the Debian package manager:
$ apt-get install memcached php5-memcached $ /etc/init.d/apache2 restart
$ yum install memcached php-pecl-memcache $ service httpd restart
You can check if the PHP extension installed correctly in phpinfo, there you should see something like:
To change the default Memcached settings, modify the file /etc/memcached.conf. This is our configuration:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
# memcached default config file # 2003 - Jay Bonci <email@example.com> # This configuration file is read by the start-memcached script provided as # part of the Debian GNU/Linux distribution. # Run memcached as a daemon. This command is implied, and is not needed for the # daemon to run. See the README.Debian that comes with this package for more # information. -d # Log memcached's output to /var/log/memcached logfile /var/log/memcached.log # Be verbose -v # Be even more verbose (print client commands as well) -vv # Start with a cap of 64 megs of memory. It's reasonable, and the daemon default # Note that the daemon will grow to this size, but does not start out holding this much # memory -m 128 # Default connection port is 11211 -p 11211 # Run the daemon as root. The start-memcached will default to running as root if no # -u command is present in this config file -u nobody # Specify which IP address to listen on. The default is to listen on all IP addresses # This parameter is one of the only security measures that memcached has, so make sure # it's listening on a firewalled interface. -l 127.0.0.1 # Limit the number of simultaneous incoming connections. The daemon default is 1024 # -c 1024 # Lock down all paged memory. Consult with the README and homepage before you do this # -k # Return error when memory is exhausted (rather than removing items) # -M # Maximize core file limit # -r # Custom - decrease wasted slab space -f 1.05 -I 128k
The difference between the default setup and our setup are the following lines:
to increase the memory available to memcached, and
-f 1.05 -I 128k
as chunks created by activeCollab are small and a lot of space in slabs is wasted with the default settings.
One more thing, activeCollab has to know which file cache to use. By default, activeCollab will use disk caching or APC. To switch it to use memcached you have to add some config options. To do this, add following lines to config/config.php:
1 2 3
const CACHE_BACKEND = 'memcached'; const CACHE_MEMCACHED_PREFIX = 'prefix_'; const CACHE_MEMCACHED_SERVERS = 'memcachedserver:port';
The testing is done on a commodity server containing a dual core Xenon (E3110) and 8G of RAM. The application environment is as follows:
- Generic MySQL 5.6.13 binaries from http://dev.mysql.com/downloads/mysql/.
- Apache 2.4.6
- PHP 5.4.19 and PHP 5.5.3 compiled from source
To stress test this environment we use ApacheBench (ab). To get the most accurate results, which will invoke calls to MySQL and get some real world data, we've run ab hitting the activeCollab projects page (loaded with a bunch of our own projects, tasks and users) over the API:
$ ab -n 500 -c 6 "http://192.168.1.212/activecollab/public/api.php?path_info=projects&auth_api_token=user-api-token"
Here are the results (averages from multiple runs)
PHP 5.4.19 + APC
- Time taken for tests: 80.253 seconds
- Requests per second: 6.23 [#/sec] (mean)
PHP 5.5.3 + OPcache + Memcached
- Time taken for tests: 78.3 seconds
- Requests per second: 6.39 [#/sec] (mean)
As we can see, PHP 5.5.x + OPcache + Memcached has a small advantage over PHP 5.4.x + APC. The way we see it, the difference is not big enough to make you change your working PHP + APC setup, but as things move forward, making the switch is unavoidable. We are glad to see that activeCollab is ready for the change.
We also plan to commence testing OPcache on our Cloud platform, first by introducing it with PHP 5.4 which now runs the cloud, later switching to PHP 5.5.x. This will be a kind of A/B testing, as not all the machines in the cluster will get this upgrade, meaning we will have a side-by-side comparison of real usage.