Building a Better PHP — Part 2: Using HHVM
Using HHVM
Continuing on from part one in our series, now that we have a working HHVM environment, we can start to use it for something more practical than phpinfo()
.
Composer
One of the first things you can do today to improve your workflow, is to start using HHVM for composer. As noted in numerous tweets. This will make composer run faster, and use less resources. And, as this is a standalone process, it is easy to switch away from PHP.net – and more importantly, switch back if things go awry.
First, lets start by installing Composer. Because HHVM defaults to a 5000ms HTTP request timeout, we will want to change this setting.
To change this, we need to set the Http.SlowQueryThreshold
configuration option.
We can set it in the server.hdf
config (affecting all requests) by adding:
Http {
SlowQueryThreshold = 30000
}
Or, we can do it via the command line using the -v
flag, or if using --php
flag to emulate PHP’s CLI, the -d
flag:
$ hhvm -v Http.SlowQueryThreshold=30000
or
$ hhvm --php -dHttp.SlowQueryThreshold=30000
Note: You may require a higher threshold depending on your internet connection
We then have to install a couple of dependencies:
$ sudo apt-get install curl git unzip
Now to install Composer, we can simply do:
$ curl -sS https://getcomposer.org/installer | sudo hhvm --php -dHttp.SlowQueryThreshold=30000
$ sudo mv composer.phar /usr/local/bin/composer
This uses the --php
flag to allow us to pipe the Composer installer code directly into HHVM.
Next, we setup an alias for composer to allow us to run it via HHVM, and to set two network configuration variables to alleviate most issues with slower connections.
Additionally, we set the Eval.Jit=false
as the JIT is only beneficial to long-running processes when used on the CLI, and would in the case of composer cause the HHVM startup to be slower.
alias composer="hhvm -v ResourceLimit.SocketDefaultTimeout=30 -v Http.SlowQueryThreshold=30000 -v Eval.Jit=false /usr/local/bin/composer"
To make this permanent, you should add this line to ~/.bashrc
and run source ~/.bashrc
.
We can then run composer
and setup our project, using for example the Zend Framework 2 Skeleton Application:
$ composer create-project --prefer-source zendframework/skeleton-application:dev-master /var/www/zf2
Note: I got an ErrorException “Undefined variable: inputStream”, however it completed successfully none-the-less.
Setting up our Web Server for Zend Framework 2
Next, we update our Nginx and hhvm server configurations to point to the ZF2 document root, /var/www/zf2/public
.
For Nginx, edit /etc/nginx/sites-available/hhvm.conf
and change the following two lines:
root /var/www/zf2/public;
# Inside the location block
fastcgi_param SCRIPT_FILENAME /var/www/zf2/public$fastcgi_script_name;
For HHVM, we change the Server.SourceRoot
configuration to:
SourceRoot = /var/www/zf2/public
Next, restart both services:
$ sudo service nginx restart
$ sudo service hhvm restart
Note: prior to the HHVM 3.0 the init scripts for Ubuntu (at least) were broken. Instead, you should use
sudo killall hhvm && sudo service hhvm start
to restart.
If you access the web server in your browser again, you will see the default ZF2 Skeleton Application:
Now you can start to develop a new ZF2 application.
PHPUnit
Another common task that can be improved by switching to HHVM is running your unit tests.
To do this, first install PHPUnit using Composer:
$ composer global require 'phpunit/phpunit=4.0.*'
To complete the installation, add the following alias to your ~/.bashrc
and run source ~/.bashrc
:
alias phpunit='hhvm -v Eval.Jit=false /home/vagrant/.composer/vendor/bin/phpunit'
Now, the phpunit
command will be run via HHVM, just like Composer.
If we want to run the ZF2 test suite, we can do so by running the following:
$ cd /var/www/zf2/vendor/zendframework/zendframework
$ composer install
$ cd tests/
$ phpunit
Using FastCGI with UNIX Sockets
With the next version of HHVM (3.0, scheduled for March 27th) we will see support for FastCGI over UNIX sockets.
UNIX Sockets should (in theory) perform better than TCP sockets, and are easy to use. If you choose to make this change, be sure to benchmark before and after the change to ensure that you are actually seeing performance increases, or resource usage decreases.
To use UNIX sockets, we again need to change our server configs. For HHVM, change /etc/hhvm/server.ini
like so:
; hhvm.server.port = 9000
hhvm.server.file_socket = /var/run/hhvm/server.sock
For Nginx, change /etc/nginx/sites-available/hhvm.conf
:
location ~ \.(hh|php)$ {
# fastcgi_pass 127.0.0.1:9000;
fastcgi_pass unix:/var/run/hhvm/server.sock;
...
}
Then just restart the daemons again:
$ service hhvm restart
$ service nginx restart
Note: To use this feature now, you must install a current nightly build (the
VagrantFile
will do this by default).
Coming up next…
As well as an overview of using HHVM to replace PHP.net, we now have two practical applications for HHVM that we can put into use immediately.
In the next part in this series, we will take an in-depth look at hack and the features it brings to the table — as well as review what they might mean for PHP.net.
Have you tried HHVM yet? What are your experiences? What do you think about HHVM so far? Let us know in the comments.
Share your thoughts with @engineyard on Twitter