HHVM ist einer der neuen Shooting-Stars beim Thema schneller Webservices. Die Alternative zum Zend PHP benötigt recht guten Code, gibt dann aber eine erhebliche Beschleunigung des Codes. Verschiedene Open Source Projekte haben in ihren Updates Kompatibilität hergestellt, unter anderem Piwik und WordPress. Bei WordPress scheitern noch zahlreiche Plugins und Themes an den Code-Standards, so dass ich HHVM bei mir zunächst nur für Piwik einsetze. Da Piwik aber aber auf jedem Blog eingesetzt wird, gibt es indirekt so trotzdem eine Beschleunigung von WordPress.
Konfiguration von HHVM mit Nginx
Eins vorweg: die Anleitung funktioniert nur mit Rootzugriff auf dem Server. Webspace-Nutzer können HHVM nicht nutzen, und bei der Verwendung von Plesk würde ich einen heftigen Krieg gegen Plesk erwarten.
HHVM muss zunächst installiert werden. Hierfür stellt das HHVM Team Pakete und eine Installationsanleitung bereit.
Ein bisschen frickelig erweist sich das Starten von verschiedenen HHVM-Instanzen unter verschiedenen Systemnutzern. Eine Umsetzung der Pools von PHP-FPM wäre wünschenswert, so braucht man ein Init-Script für jede HHVM-Instanz. Ein Beispielscript liegt bereits in /etc/init.d/hhvm vor, das passen wir ein wenig an. Also:
cp /etc/init.d/hhvm /etc/init.d/hhvm-piwik
Dann passen wir die Datei hhvm-piwik an. Ich verwende dabei einen eigenen Ordner in /var/run/ für Socket und Pid, welcher ggf. erstellt wird (siehe Ergänzungen bei do_start() ):
PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="HHVM FastCGI Daemon - Piwik"
NAME=hhvm-piwik
DAEMON=/usr/bin/hhvm
PIDFILE=/var/run/hhvm-piwik/pid
SCRIPTNAME=/etc/init.d/$NAME
# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0
# Default values. This values can be overwritten in '/etc/default/hhvm'
CONFIG_FILE="/etc/hhvm/server-piwik.ini"
SYSTEM_CONFIG_FILE="/etc/hhvm/php.ini"
RUN_AS_USER="piwik"
RUN_AS_GROUP="piwik"
ADDITIONAL_ARGS=""
[...]
check_run_dir() {
# Only perform folder creation, if the PIDFILE location was not modified
PIDFILE_BASEDIR=$(dirname ${PIDFILE})
}
do_start()
{
# Return
# 0 if daemon has been started
# 1 if daemon was already running
# 2 if daemon could not be started
mkdir -p -m0755 /var/run/$NAME
chown $RUN_AS_USER:$RUN_AS_GROUP /var/run/$NAME
mkdir -p -m0755 /var/log/hhvm/piwik
chown $RUN_AS_USER:$RUN_AS_GROUP /var/log/hhvm/piwik
touch $PIDFILE
chown $RUN_AS_USER:$RUN_AS_GROUP $PIDFILE
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
|| return 1
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \
$DAEMON_ARGS \
|| return 2
}
Die unter CONFIG_FILE erwähnte Datei /etc/hhvm/server-piwik.ini müssen wir natürlich auch erstellen. Dort lege ich auch fest, dass ich statt TCP/IP eine Unix Socket verwende:
; php options
pid = /var/run/hhvm-piwik/pid
; hhvm specific
hhvm.server.file_socket = /var/run/hhvm-piwik/hhvm.sock
hhvm.server.type = fastcgi
hhvm.server.default_document = index.php
hhvm.log.use_log_file = true
hhvm.log.file = /var/log/hhvm/piwik/error.log
hhvm.repo.central.path = /var/run/hhvm-piwik/hhvm.hhbc
Nachdem diese beiden Dateien erstellt wurden müsste HHVM via service hhvm-piwik start zu starten sein. Nach einigen Sekunden kann man dann mit service hhvm status den Status abfragen. Zur Fehlerbehebung liegen Logs in /var/log/hhvm bereit. Wenn da nicht genug steht hilft es, HHVM direkt ohne –mode daemon zu starten, dann bekommt man die Fehlermeldungen direkt in die Shell geschrieben.
Jetzt müssen wir noch in der Nginx Konfiguration auf HHVM statt auf PHP-FPM verweisen. Dies kann man abhängig vom virtuellen Host machen. In meinem Fall liegt die Datei in /etc/nginx/sites-available/piwik:
server {
[...]
location ~ \.php$ {
try_files $uri = 404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
#fastcgi_pass unix:/var/run/php5-piwik.sock;
fastcgi_pass unix:/var/run/hhvm-piwik/hhvm.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
}
[...]
}
Die auskommentierte Zeile ist das alte PHP-FPM, die Zeile darunter ist HHVM. Mit einem service nginx configtest können wir die neue Konfiguration testen, mit service nginx restart aktivieren. Jetzt müsste HHVM aktiv sein.
Um HHVM nun beim Neustart gleich mitzustarten fehlt nun noch ein Update der RC-Scripte. Dies geht mit dem Befehl sudo update-rc.d hhvm-piwik defaults . Danach sollten alle Symlinks korrekt gesetzt sein.
Resultat: Erheblich mehr Geschwindigkeit durch HHVM!
Hat der ganze Aufwand etwas gebracht? Ein ganz klares ja. Die Oberfläche von Piwik ist nun erheblich schneller. Der Tracking-Code in WordPress ist ebenfalls deutlich schneller. Und auch mit Apache ab lassen sich erhebliche Unterschiede feststellen. Der erste Test ist mit HHVM, der zweite Test mit PHP-FPM:
# ab -n 100 https://piwik.sectio-aurea.org/
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking piwik.sectio-aurea.org (be patient).....done
Server Software: nginx/1.1.19
Server Hostname: piwik.sectio-aurea.org
Server Port: 443
SSL/TLS Protocol: TLSv1/SSLv3,ECDHE-RSA-AES256-SHA,4096,256
Document Path: /
Document Length: 20607 bytes
Concurrency Level: 1
Time taken for tests: 6.484 seconds
Complete requests: 100
Failed requests: 0
Write errors: 0
Total transferred: 2097000 bytes
HTML transferred: 2060700 bytes
Requests per second: 15.42 [#/sec] (mean)
Time per request: 64.840 [ms] (mean)
Time per request: 64.840 [ms] (mean, across all concurrent requests)
Transfer rate: 315.83 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 21 23 5.2 21 52
Processing: 37 42 8.6 39 88
Waiting: 24 40 8.8 39 88
Total: 59 65 13.1 61 125
Percentage of the requests served within a certain time (ms)
50% 61
66% 62
75% 62
80% 64
90% 70
95% 106
98% 122
99% 125
100% 125 (longest request)
# ab -n 100 https://piwik.sectio-aurea.org/
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking piwik.sectio-aurea.org (be patient).....done
Server Software: nginx/1.1.19
Server Hostname: piwik.sectio-aurea.org
Server Port: 443
SSL/TLS Protocol: TLSv1/SSLv3,ECDHE-RSA-AES256-SHA,4096,256
Document Path: /
Document Length: 20607 bytes
Concurrency Level: 1
Time taken for tests: 20.895 seconds
Complete requests: 100
Failed requests: 0
Write errors: 0
Total transferred: 2097600 bytes
HTML transferred: 2060700 bytes
Requests per second: 4.79 [#/sec] (mean)
Time per request: 208.952 [ms] (mean)
Time per request: 208.952 [ms] (mean, across all concurrent requests)
Transfer rate: 98.03 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 21 24 6.5 22 54
Processing: 141 184 82.4 149 456
Waiting: 125 165 75.3 133 419
Total: 162 209 87.7 171 497
Percentage of the requests served within a certain time (ms)
50% 171
66% 174
75% 178
80% 199
90% 355
95% 467
98% 493
99% 497
100% 497 (longest request)
6,4 Sekunden vs. 20,8 Sekunden sprechen eine sehr deutliche Sprache. Ebenso eine sehr deutliche Sprache spricht die Tatsache, dass der schnellste Request bei PHP-FPM langsamer ist als der langsamste bei HHVM. Und auch in der Praxis wirkt es: meine WordPress-Seiten sind ca. 200 ms schneller geworden, da Piwik schlicht nicht mehr so lange braucht.
Ich wünsche viel Spaß beim Einrichten und freue mich über Kommentare und Ergänzungen!
Bei der aktuellen Piwik-Version dauert die Auslieferung meiner piwik.php bereits über 600ms, während dein Server nur ~173ms braucht (Backend kann ich natürlich nicht vergleichen). Auch die piwik.js ist auch in letzter Zeit wahnsinnig gewachsen, fällt aber dank gzip nicht so sehr ins Gewicht. Wenn ich hingegen einen Benchmark von letztem Jahr rauskrame, dann liegt mein stinkealter managed vserver (Apache) noch vor deinem Piwik-Server.
Wer’s auf Frontend-Performance anlegt, könnte eventuell das asynchrone Tracking einsetzen. Mir war aber vor allem das Backend zu langsam. Werde mich in Kürze auf jeden Fall nach einer Alternative umsehen müssen, weil mein PHP 5.3 ausläuft. Doch bereis mit dem Installieren von HHVM bin ich grandios gescheitert. Wahrscheinlich werde ich mir vorübergehend ein managed nginx php-fpm Hosting mit APCu & Memcached holen und später auf das vielversprechende PHP7 upgraden. Ich bin auch noch nicht auf die neuerdings vom Piwik Team empfohlene Datenbank-Engine umgestiegen; Muss unbedingt mal testen, ob das was bringt.
Spannender Fakt: Ein Dedicated Core i5 Server hatte eine spürbar schwächere Piwik-Backend-Performance als der oben genannte billige vserver. Offenbar spielt die sorgfältige Konfiguration eine überaus wichtige Rolle. Hochoptimierte Systeme dürften auch nicht so anfällig für DDOS Attacken sein. Und noch ganz viele andere Vorteile wie SEO, Benutzerzufriedenheit und mehr.
Die 173 ms sind allerdings spannend, da das ja eigentlich nur eine statische Datei ist, das sollte schneller gehen. Wenn ich Zeit habe schaue ich da mal genauer hin. Aber meins ist schon ein aktuelles Piwik. Das Backend ist mit HHVM allerdings auch n gutes Stück fixer geworden. Und was parallel unglaublich viel gebracht hat beim Backend: die MySQL my.conf mittels mysqltuner Schritt für Schritt anpassen.
Dass ein i5 nicht gegen einen XEON-basierten vServer ankommt wundert mich dagegen weniger. Serverhardware ist nicht umsonst ein paar Cent teurer. 🙂 Und es hängt natürlich auch extreeeeeem vom Server (Anbieter) ab.
[…] Maßnahme, um Shariff zu beschleunigen, ist der alternative PHP-Interpreter HHVM. Dieser macht z.B. auch bei Piwik eine großartige Arbeit, setzt aber sauberen Code voraus. Glücklicherweise wird heise seinem guten Ruf gerecht und […]