WordPress apache & hhvm [en]

Update 07-02-2016

There are now package manager repositories for hhvm which greatly simplify the installation process see: https://docs.hhvm.com/hhvm/installation/introduction

Want to use WordPress but pages load to slow?
Now you can improve your WordPress performance by miles,
With the HipHop virtual machine!

HipHop virtual machine is fully compatible with apache and wordpress!

The hiphop virtual machine is an JIT ( just in time ) compiler for php running in a virtual machine. It is just like how java is operating. Instead of interpreting php and turning it into series of opt-codes. hhvm turns php into intermediate byte-code before translating it into x64 machine code. This is what gives hhvm its impressive speed compared to traditional php. hhvm is still in active development by Facebook, and as of right now there is no windows version. More information can be found on github or there website.

wordpress stopwatch speed increase

hhvm test results

I couldn’t resist but to try it for myself, using a virtual machine I installed all the necessary components to compare the regular php interpreter to Facebooks hhvm. I was very pleased with the results, Working with WordPress websites for a few years I have come to know that php can be dreadfully slow. For the test I have set up an empty WordPress site with:

  • Ubuntu 10.04 x64 LTS
  • Apache 2.2
  • Mysql 14.14
  • WordPress 4.0.1
  • PHP 5.3
  • HHVM 3.2

The results are for the time it took before the html was returned by the server, time is measured in milliseconds. Of course when HHVM is used PHP is not used and vice versa. For the test I performed 10 page request the response time was monitored in Google Chrome developer tools.

Request hhvm interpreter
Request 1 44ms 149ms
Request 2 34ms 134ms
Request 3 36ms 126ms
Request 4 36ms 175ms
Request 5 35ms 113ms
Request 6 35ms 115ms
Request 7 35ms 114ms
Request 8 68ms 152ms
Request 9 34ms 118ms
Request 10 65ms 117ms
Average 42.2ms 131.3ms
These results show a 311% performance improvement, Which considering we did no further optimization then changing the default interpreter for hhvm is astonishing. Now nothing is wrong with a 130ms page request, however when the number of plug-ins climb up, the total amount of pages and posts increases and a more complex theme is used. The time required for a page request in WordPress can increase drastically.

Setting it up

To set it up it is recommend to have apache installed, this is out of the scope of this tutorial. The main reason for this is that there are plenty of tutorials to install apache. If you do install apache do yourself a favor and install apache 2.2 and not 2.4. If you do have 2.4 installed and run in to trouble scroll down to troubleshooting with apache 2.4. To get started we must install hhvm, If your platform is one of the following:

Ubuntu 10.04
Ubuntu 12.04
Ubuntu 13.04
Ubuntu 13.10
Ubuntu 14.04
Ubuntu 14.10
Debian 7
Debian 8
Fedora 19
Fedora 20
Mint 15
Centos 6.X
Amazon linux

Then you can use the Prebuilt hhvm package avaiable at:
https://github.com/facebook/hhvm/wiki/Prebuilt%20Packages%20for%20HHVM
If your out of luck and this is not the case you will have to compile hhvm from source, which is beyond the scope of this tutorial. Detailed tutorials for many different distro’s can be found here:
https://github.com/facebook/hhvm/wiki/Building-and-Installing-HHVM
After you used either an prebuild package or compiled hhvm from source, Make sure its working by using the command:
php -v
This should return something that looks like:

HipHop VM 3.2.0 (rel)
Compiler: tags/HHVM-3.2.0-0-g01228273b8cf709aacbd3df1c51b1e690ecebac8
Repo schema: c52ba40f4a246d35a88f1dfc1daf959851ced8aa

If you havent done this already you can execute: sudo update-rc.d hhvm defaults to make hhvm start at boot. The current recommend method for using HHVM is an fastcgi server. This requires the fastcgi module as-well as the rewrite, alias and proxy modules. To enable them you can use the following commands.
sudo a2enmod fastcgi
sudo a2enmod rewrite
sudo a2enmod alias
sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod proxy_fcgi
sudo a2enmod actions

Most apache installs come without the fastcgi module, If the sudo a2enmod fastcgi command failed first install fastcgi with: sudo apt-get install libapache2-mod-fastcgi. Then execute the command again. To be able to use rewrite rules in your htaccess or vhost file, the following configuration line for HHVM is required.
hhvm.server.fix_path_info = true
you can add this to the hhvm server.ini located in./etc/hhvm/
Removing the X-Powered-by header is also a good idea, We do this with the following configuration line for the server.ini file expose_php=off. The total configuration file will look like:

; php options

pid = /var/run/hhvm/pid

; hhvm specific

hhvm.server.port = 9000
hhvm.server.type = fastcgi
hhvm.server.default_document = index.php
hhvm.log.use_log_file = true
hhvm.log.file = /var/log/hhvm/error.log
hhvm.repo.central.path = /var/run/hhvm/hhvm.hhbc
hhvm.server.fix_path_info = true
expose_php=off

With hhvm properly configured and the required apache modules active, The only thing we have to change is our vhost configuration, Apache needs to know to use the fastcgi server for parsing php files instead of the default php interpreter. To do this add the following lines to your vhost file:

<IfModule mod_fastcgi.c>
<FilesMatch \.php$>
SetHandler hhvm-php-extension
</FilesMatch>

<FilesMatch \.hh$>
SetHandler hhvm-hack-extension
</FilesMatch>

Alias /hhvm /hhvm
Action hhvm-php-extension /hhvm virtual
Action hhvm-hack-extension /hhvm virtual

FastCgiExternalServer /hhvm -host 127.0.0.1:9000 -pass-header Authorization -idle-timeout 300
</IfModule>

To use /hhvm as an directory within our webserver we need to add the following lines to our configuration:

<Location /hhvm>
Order Deny,Allow
Deny from All
Allow from env=REDIRECT_STATUS
</Location>

Many apache configurations use rewrite rules, WordPress uses them by default. To enable rewrite rules add:

RewriteRule ^(.*)\.php$ http://127.0.0.1:88/$1.php [L,P]
ProxyPassReverse / http://127.0.0.1:88/s

If you use apache 2.4 you will need to add: required all granted to the directory of your vhost, This is a new security measure in apache 2.4.
In my case the total vhost file looked like:

<VirtualHost *:80>
ServerAdmin webmaster@localhost

DocumentRoot /var/www
<Directory />
Options FollowSymLinks
AllowOverride all
require all granted
</Directory>
<Directory /var/www/>
Options Indexes FollowSymLinks MultiViews
AllowOverride all
Order allow,deny
allow from all
require all granted
</Directory>

ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
<Directory “/usr/lib/cgi-bin”>
AllowOverride None
Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
Order allow,deny
Allow from all
</Directory>

ErrorLog /var/log/apache2/error.log
LogLevel warn
CustomLog /var/log/apache2/access.log combined

<IfModule mod_fastcgi.c>
<FilesMatch \.php$>
SetHandler hhvm-php-extension
</FilesMatch>

<FilesMatch \.hh$>
SetHandler hhvm-hack-extension
</FilesMatch>

Alias /hhvm /hhvm
Action hhvm-php-extension /hhvm virtual
Action hhvm-hack-extension /hhvm virtual

FastCgiExternalServer /hhvm -host 127.0.0.1:9000 -pass-header Authorization -idle-timeout 300
</IfModule>
<Location /hhvm>
# here we prevent direct access to this Location url,
# env=REDIRECT_STATUS will let us use this “/hhvm” url
# only after an internal redirect (by Action upper)
Order Deny,Allow
Deny from All
Allow from env=REDIRECT_STATUS
</Location>

RewriteRule ^(.*)\.php$ http://127.0.0.1:88/$1.php [L,P]
ProxyPassReverse / http://127.0.0.1:88/s
</VirtualHost>

Now to let all changes take affect run the following commands:
sudo /etc/init.d/hhvm restart
sudo /etc/init.d/apache2 restart
Now you should be able to use your webserver just like before, But now with much better performance. According to the Facebook developers of hhvm: performance should increase with 200% to 2000% which is an amazing performance improvement.

Additional tips & tricks

By default HHVM has no error reporting to the user. Meaning that errors wont be displayed on the webpage. Instead all errors are written to the log, which by default is located in /var/log/hhvm To some extent this could slow down debugging. To display php errors again we need to override the error handler. Do this by adding the following function to your php files:

set_error_handler(function ($errorNumber, $message, $errfile, $errline) {
switch ($errorNumber) {
case E_ERROR :
$errorLevel = ‘Error’;
break;

case E_WARNING :
$errorLevel = ‘Warning’;
break;

case E_NOTICE :
$errorLevel = ‘Notice’;
break;

default :
$errorLevel = ‘Undefined’;
}

echo ‘<br/><b>’ . $errorLevel . ‘</b>: ‘ . $message . ‘ in <b>’.$errfile . ‘</b> on line <b>’ . $errline . ‘</b><br/>’;
});

To make most use out of this you should also set:
error_reporting = e_all
In the hhvm php.ini file located in /etc/hhvm/, It is important to note that critical errors will still leave you with a blank page. This is because HHVM actually compiles php when the compiler meets an critical error it will halt the compilation, So when your page stays blank to look at the errors you will still need to look in the error.log in /var/log/hhvm.
Finally this kind of error reporting should never be used in a production environment, so be sure to remove these changes before you take it into production!

Troubleshooting with apache 2.4

So if you read this odds are something is not working. So first off all apache 2.4 requires a other implementation method for hhvm start by enabling extra required modules: sudo a2enmod proxy-fcgi. With this enabled we can go ahead an change our vhost configuration, add this line: ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9000/path/to/root/$1. This line replaces the entire part in <IfModule mod_fastcgi.c>, Be sure to replace /path/to/root/ with your own root directory. Now for the disappointing part .htaccess files probably don’t work. So any additional configuration will need to be placed into the vhost file itself, You can this like so:

<Directory />
Options +FollowSymLinks -MultiViews
AllowOverride all
Order allow,deny
allow from all
Require all granted
RewriteEngine on
RewriteRule ^index\.php$ – [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</Directory>

Im looking into how to load .htaccess with apache 2.4 & hhvm but for now this is a safe bet.
If you have any question or problems feel free to leave a comment.

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *

*