Deploy a faster WordPress with HHVM and PHP-FPM as fallback

We just released a WordPress container with HHVM and PHP-FPM as a fallback. The container can be used to test and experiment with HHVM and a base to run PHP apps. This container is in addition to the normal WordPress container,  and the recently released preview WordPress micro container.

For new users Flockport containers are based on the open source LXC project and you can Get Started on our Documentation page. Here is a quick screencast of the WordPress container in action.

So what's HHVM?
HHVM is the new much talked up PHP stack by Facebook. HHVM is an open-source virtual machine designed for executing PHP programs and uses a just-in-time (JIT) compilation approach to try to achieve superior performance.

Currently the project is in rapid development to gain 100% compatibility with PHP apps and improve performance.

Faster PHP?
Early reports are promising. The benchmarks suggest its significantly faster than stock PHP. For apps like WordPress some users and popular hosts like WP Engine report 3x to 5x speed improvements with HHVM compared to stock PHP.

Benchmarks do not always indicate real world performance and there are some caveats that early adopters need to be aware of though.

PHP Compatibility
HHVM is not yet compatible with all PHP workloads. WordPress for instance is 100 percent compatible from version 4.0, but that does not include the ecosystem of plugins and themes, and short of a registry there is no way to know compatibility without experimenting.

Similarly a lot other projects like Drupal, Typo3 etc are on the way to becoming HHVM compatible.

HHVM Caveats
HHVM is in active development and there have been reports of memory leaks. This means long running php processes can result in the HHVM process bloating, consuming ridiculous amounts of ram and crashing. The good news is the HHVM developers are extremely responsive and are working hard to iron out all issues.

My tests on HHVM version 3.4 has been stable so far and the process has been alive for 48 hours with around 380MB RAM usage but this is not a real world scenario with loads and spikes.

The work around is to use a cron job or a process manager like Supervisord to periodically restart the HHVM process every  couple of hours.

HHVM is memory intensive and works best with dynamic workloads. Also HHVM uses threads unlike php-fpm which uses worker processes. So in top or htop you will see a single HHVM process as opposed to the multiple php-fpm processes.

HHVM and PHP-FPM
PHP-FPM with Nginx is reasonably fast. With PHP 5.4 APC offered significant performance improvements. PHP 5.5 ships with Zend Opcache, which in benchmarks shows better performance than APC. There is also PHPNG in the works which in benchmarks show much faster performance than PHP 5.4 or PHP 5.5 but still slower than HHVM.

HHVM initially had an internal server that was a bit difficult to work with, but now works in FastCGI mode so those using php-fpm with Nginx can simply direct the socket or tcp port to HHVM FastCGI.

Installing HHVM is fairly straight forward. The HHVM project provides official binaries for Ubuntu, Debian and Mint. There are unoffical binaries for CentOS. Fedora and Amazon Linux. This problem is easily solved by installing HHVM in an LXC container of a supported distribution.

The performance improvements hhvm bring is to the execution of php code, so dynamic sites stand to benefit the most. If you are serving mainly static pages from a cache then hhvm won't really help you. But for logged in users and ecommerce stores for instance where full page caching is not a possibility, hhvm can deliver improved performance with reduced latency.

Flockport WordPress HHVM container with PHP-FPM fallback

The Flockport HHVM container is an easy way to try HHVM. The container ships with WordPress 4.1, HHVM 3.4 and php-fpm 5.4 with APC as a fallback. You can download the container to experiment and benchmark HHVM for your PHP workloads.

To learn how to install and use LXC and Flockport containers please head over to our Getting started and Documentation page.

HHVM does not support i386 so there are no 32 bit containers. HHVM by default is available on port 9000. So for those using PHP-FPM its a simple matter of stopping the PHP-FPM process and starting hhvm for a seamless switchover.

However we want to use php-fpm as a fallback so we have configured HHVM to be available on port 8000. Nginx is setup to use HHVM on port 8000 and php-fpm on port 9000 as a fallback.

This is how HHVM is configured and PHP-FPM configured as a fallback.

upstream php {
        # server unix:/run/php5-fpm.sock;
        server 127.0.0.1:8000; 
        server 127.0.0.1:9000 backup;
}
location ~ \.php$ {
                try_files $uri =404;
                include fastcgi_params;
                fastcgi_pass php;                ;
        }

As you can see we define an upstream 'php' in Nginx and then in the php config section the fastcgi_pass is directed to this upstream 'php'. HHVM is configured to be available on port 8000 and we have left php-fpm in its default port 9000 and configured it as a backup.

The HHVM configuration to change fastcgi port etc is in /etc/hhvm/server.ini. The upstream php block can be in your server configuration or can be placed as a separate file in the /etc/nginx/conf.d directory. We have placed it in the conf.d directory as upstream.conf.

We often use the easyengine script to setup our WordPress containers and use the Nginx config layout. You can of course configure to your preference.

Quick benchmarks with Siege
Here are some quick benchmarks using the popular benchmarking tool Siege. The server is a 1GB KVM instance with 1 vcpu. We benchmarked WordPress 4.1 running PHP 5.4 with APC, PHP 5.5 with Zend Opcache and HHVM 3.4.2.

The Siege command line used is below. APC and Opcache were allocated 128MB.

siege mywordpress.org -d1 -c50 -r100 -t24S

PHP 5.4 with APC

Transactions:		         997 hits
Availability:		      100.00 %
Elapsed time:		       23.93 secs
Data transferred:	        2.14 MB
Response time:		        0.67 secs
Transaction rate:	       41.66 trans/sec
Throughput:		        0.09 MB/sec
Concurrency:		       27.97
Successful transactions:         997
Failed transactions:	           0
Longest transaction:	        0.96
Shortest transaction:	        0.17

PHP 5.5 with Zend Opcache

Transactions:		         969 hits
Availability:		      100.00 %
Elapsed time:		       24.00 secs
Data transferred:	        2.23 MB
Response time:		        0.70 secs
Transaction rate:	       40.38 trans/sec
Throughput:		        0.09 MB/sec
Concurrency:		       28.14
Successful transactions:         969
Failed transactions:	           0
Longest transaction:	        1.00
Shortest transaction:	        0.20

HHVM 3.4

Transactions:		        2284 hits
Availability:		      100.00 %
Elapsed time:		       23.72 secs
Data transferred:	        5.26 MB
Response time:		        0.03 secs
Transaction rate:	       96.29 trans/sec
Throughput:		        0.22 MB/sec
Concurrency:		        2.74
Successful transactions:        2284
Failed transactions:	           0
Longest transaction:	        0.27
Shortest transaction:	        0.00

The WordPress default page is not the best benchmark but this is just to get a quick indicator of performance. The results are in line with most HHVM benchmarks online. The performance is nearly 2x with huge gains in response time with HHVM.

Now here is the result with Nginx FastCGI cache enabled. Since the FastCGI cache does not touch the php stack there will be nearly no difference between the stacks.

Transactions:		        2355 hits
Availability:		      100.00 %
Elapsed time:		       23.85 secs
Data transferred:	        5.42 MB
Response time:		        0.00 secs
Transaction rate:	       98.74 trans/sec
Throughput:		        0.23 MB/sec
Concurrency:		        0.04
Successful transactions:        2355
Failed transactions:	           0
Longest transaction:	        0.02
Shortest transaction:	        0.00

As you can see caching is essential for maximum performance. The Nginx FastCGI cache stores accessed pages in its own cache and does not touch the php stack and can serve it extremely fast, so for full page caching it will always be faster and more efficient than other caching solutions offered.

We repeated the benchmark on a more challenging WordPress page, this time with the popular Salient WordPress theme. Here are the results.

PHP 5.4 with APC

Transactions:                 260 hits
Availability:                 100.00 %
Elapsed time:                 23.11 secs
Data transferred:             3.55 MB
Response time:                3.58 secs
Transaction rate:             11.25 trans/sec
Throughput:                   0.15 MB/sec
Concurrency:                  40.25
Successful transactions:      260
Failed transactions:          0
Longest transaction:          6.27
Shortest transaction:         0.1

HHVM

Transactions:                594 hits
Availability:                100.00 %
Elapsed time:                23.96 secs
Data transferred:            8.01 MB
Response time:               1.41 secs
Transaction rate:            24.79 trans/sec
Throughput:                  0.33 MB/sec
Concurrency:                 35.03
Successful transactions:     594
Failed transactions:         0
Longest transaction:         3.30
Shortest transaction:        0.08

HHVM is 2x stock PHP with much lower response time but clearly this is a more challenging WordPress page with many elements. Let's see Nginx FastCGI performance on this.

Transactions:                2331 hits
Availability:                100.00 %
Elapsed time:                23.71 secs
Data transferred:            31.44 MB
Response time:               0.02 secs
Transaction rate:            98.31 trans/sec
Throughput:                  1.33 MB/sec
Concurrency:                 1.52
Successful transactions:     2331
Failed transactions:         0
Longest transaction:         2.85
Shortest transaction:        0.00

As expected Nginx FastCGI cache does not break a sweat.

Install HHVM in your own container or system

It's easier to use the Flockport HHVM container but for those who would like to install and use HHVM in their existing containers or systems here is a quick overview.

Follow the HHVM install guide. After install run the hhvm fastcgi install script from /usr/share/hhvm/install_fastcgi.sh

At this point HHVM is installed but not started. If you are already using php-fpm you can choose to use it as a backup to hhvm or use only hhvm.

To use hhvm with php-fpm as a backup head to /etc/hhvm/server.ini and change the port to 8000 so php-fpm can continue to run on port 9000. To run only hhvm leave the hhvm port at its default 9000 and stop your php-fpm process.

The HHVM install FastCGI script drops a hhvm.conf file in your Nginx directory. This is how it looks

location ~ \.php$ {
    fastcgi_keep_conn on;
    fastcgi_pass   127.0.0.1:9000;
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include        fastcgi_params;
}

Copy those settings to your server config under the php section or include hhvm.conf and you are good to go. If you would like to run php5-fpm as a backup then add an upstream section to your server config like below

upstream php {
server 127.0.0.1:8000;
server 127.0.0.1:9000 backup;
}

Now in your php section modify the fastcgi_pass directive to point to your just defined upstream 'php'

location ~ \.php$ {
    fastcgi_keep_conn on;
    fastcgi_pass   php;
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include        fastcgi_params;
}

Remember you can define any name in upstream (we used 'php') as long as you use the same name in the fastcgi_pass directive.

Restart Nginx, php5-fpm and HHVM and you should be all set to try out HHVM.

Stay updated on Flockport News

Recommended Posts

Leave a Comment

Login

Register | Lost your password?