Piwik beschleunigen mit HHVM

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!

3 Antworten zu “Piwik beschleunigen mit HHVM”

  1. 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.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.