Du hast deinen AdBlocker an?

Es wäre ein Traum, wenn du ihn für t3n.de deaktivierst. Wir zeigen dir gerne, wie das geht. Und natürlich erklären wir dir auch, warum uns das so wichtig ist. Digitales High-five, deine t3n-Redaktion

t3n 36

HipHop für PHP: Erste Schritte mit der HipHop-Virtual-Machine

HipHop für PHP. (Grafik: simonox / iStock)

Mit der Größe und Komplexität vieler PHP-Applikationen sind in den letzten Jahren auch die Anforderungen an die Leistungsfähigkeit und den Ressourcenverbrauch der PHP-Laufzeitumgebung selbst gestiegen. Abhilfe verspricht die HipHop-Virtual-Machine, die sich für beliebige PHP-Applikationen nutzen lässt.

Facebook entwickelte die HipHop-Virtual-Machine (HHVM) als PHP-zu-C++-Transpiler. Sie sollte PHP-Applikationen in nativen Maschinencode übersetzten und so Performance gewinnen sowie Server-Ressourcen einsparen. Aktuelle HHVM-Versionen arbeiten mit einem Just-in-Time-Compiler, um PHP-Code zur Laufzeit in Maschinencode zu übersetzen. Zudem unterstützt HHVM seit kurzem den FastCGI-Standard, sodass sich HHVM zusammen mit einem Standard-Webserver wie Apache oder Nginx betreiben lässt (genau wie PHP-FPM). Die im März erschienene Version 3.0 unterstützt außerdem Hack, den statisch typisierten Dialekt der Programmiersprache PHP.

Wie funktioniert HipHop-Virtual-Machine?

Im Vergleich zur Zend Engine, die man in der klassischen Version des PHP-Interpreters einsetzt, verwendet die HipHop-VM ein deutlich anderes Modell zur Code-Ausführung. Die folgende Grafik zeigt den herkömmlichen Ablauf, nach dem der PHP-Interpreter ein PHP-Skript ausführt.

Ablauf der Ausführung eines PHP-Programms mit der Zend Engine.
Ablauf der Ausführung eines PHP-Programms mit der Zend Engine.

Beim Kompilieren des PHP-Codes wandelt der PHP-Interpreter den Quelltext in ein Zwischenformat um, welches aus so genannten PHP-Opcodes besteht, wie die folgende Abbildung zeigt. Dieser Zwischencode erinnert an Maschinencode. Er wird anschließend interpretiert und ausgeführt.

Ein „Hallo Welt“-Programm und die dazugehörigen PHP-Opcodes.
Ein „Hallo Welt“-Programm und die dazugehörigen PHP-Opcodes.

Jeder Mausklick in einer Web-Applikation, der ein PHP-Skript ausführt, löst diese vier Schritte standardmäßig aus. Das ist nicht sonderlich effizient. Denn das Skript liest Quelldateien jedes mal aufs Neue ein, parst sie und kompiliert sie in Opcodes – obwohl sich die Quelldateien (und damit auch die kompilierten Opcodes) in Produktivsystemen nur selten ändern. Um diesen Vorgang zu beschleunigen, setzten Entwickler häufig Opcode-Caches wie APC oder Zend Opcache ein. Letzterer ist seit Version 5.5 sogar fest in PHP eingebaut. Die Caches speichern die erzeugten Opcodes; ein PHP-Skript muss dann nur noch die Opcodes aus dem Cache laden. Die folgende Grafik zeigt dies schematisch.

Opcode-Caches speichern die Opcodes zwischen und geben sie aus, sobald das PHP-Skript erneut abläuft.
Opcode-Caches speichern die Opcodes zwischen und geben sie aus, sobald das PHP-Skript erneut abläuft.

HHVM wählt einen ähnlichen Ansatz, geht jedoch einige Schritte weiter: Sie übersetzt PHP-Quelltext zunächst in HipHop-Bytecode, bevor sie ihn wie gewohnt interpretiert und – wie bei einem Opcode-Cache – speichert. Ein Just-in-Time-Compiler übersetzt häufig ausgeführte Teile des Programms jedoch in nativen Maschinencode, den HHVM anschließend nicht mehr interpretieren muss, sondern direkt auf der CPU ausführen kann, wie die Schematik unten zeigt.

Ablauf der Ausführung eines PHP-Programms unter HHVM.
Ablauf der Ausführung eines PHP-Programms unter HHVM.

Indem das Kompilieren zur Laufzeit stattfindet (und nicht ahead-of-time), kann HHVM den Bytecode aufgrund von Informationen optimieren, die sie zur Laufzeit gewonnen hat. Mögliche Code-Optimierungen können beispielsweise sein, dass für häufig aufgerufene Funktionen eine Inline-Ersetzung stattfindet – oder dass HHVM – trotz der dynamischen Typisierung von PHP – bestimmte Annahmen darüber trifft, welche speziellen Datentypen die Variablen während der Laufzeit wahrscheinlich annehmen.

Schnellstart: HHVM mit Nginx

Für die am meisten verbreiteten Linux-Distributionen (Debian, Ubuntu, CentOS, Fedora) gibt es fertige Pakete, die man über die Paketverwaltung des Betriebssystems installieren kann. Unter Debian 7 ist eine Installation von HHVM etwa wie folgt möglich:

Installation von HHVM unter Debian Wheezy:

wget -O - http://dl.hhvm.com/conf/hhvm.gpg.key | apt-key add -
echo deb http://dl.hhvm.com/debian wheezy main > /etc/apt/sources.list.d/hhvm.list
apt-get update
apt-get install hhvm

Listing 1

Wagemutige können HHVM auch selbst aus den Quellen kompilieren. Hierfür sollte man jedoch ein wenig Geduld mitbringen. Wer einfach die neueste (aber nicht notwendigerweise stabile) Version nutzen möchte, kann auch das Paket hhvm-nightly aus den Paketquellen installieren.

Ist ein Webserver (Apache oder Nginx) bereits installiert, konfiguriert der HHVM-Installationsprozess diesen praktischerweise vollautomatisch. Bei Nginx sieht die entsprechende Konfigurationsdatei unter /etc/nginx/hhvm.conf folgendermaßen aus:

Standard-Konfiguration für HHVM als FCGI-Backend unter Nginx

:

location ~ \.(hh|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;
}

Listing 2

In der eigentlichen Virtual-Host-Konfiguration von Nginx muss man diese Konfiguration anschließend nur einbinden und das URL-Rewriting konfigurieren. Folgende minimale Konfigurationsdatei funktioniert für TYPO3 CMS und für TYPO3 Neos:

Virtual-Host-Konfiguration für nginx:

server {
    root /path/to/typo3;
    server_name mydomain.local;

    index index.php;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    include /etc/nginx/hhvm.conf;

    # Nur für TYPO3 Flow-Applikationen:
    fastcgi_param FLOW_CONTEXT Production;
    fastcgi_param FLOW_REWRITEURLS 1;
}

Listing 3

Nach der Installation sollte man noch beide Dienste mit „service hhvm start“ und „service nginx restart“ starten.

Anwendungskompatibilität

Wer bestehende PHP-Anwendungen unter HHVM betreiben möchte, sollte daran denken, dass HHVM (noch) nicht zu 100 Prozent kompatibel mit PHP 5 ist; einige Funktionen, die unter PHP 5 gut funktionieren, tun dies nicht auch notwendigerweise unter HHVM. Das kann sich auf unterschiedliche Weise äußern: Bei TYPO3 CMS funktioniert das Seiten-Rendering auch unter HHVM einwandfrei. Allerdings ist kein Login ins Backend möglich, da der Algorithmus zum Hashen der Passwörter unter HHVM nicht fehlerfrei arbeitet.

TYPO3 Flow und Neos quittieren sogar sofort den Dienst. Ihr Quelltext verwendet einige Sprachkonstrukte, die HHVM derzeit nicht unterstützt. Für TYPO3 Neos und Flow steht jedoch ein Patch in Form eines Composer-Packages bereit.

Gemessene Transaktionsraten von HHVM 3.0.1 und PHP 5.5.3 bei 500 parallelen Benutzern: HHVM kann im Vergleich zu PHP-FPM die drei- bis vierfache Menge an Anfragen pro Sekunde bearbeiten
Gemessene Transaktionsraten von HHVM 3.0.1 und PHP 5.5.3 bei 500 parallelen Benutzern: HHVM kann im Vergleich zu PHP-FPM die drei- bis vierfache Menge an Anfragen pro Sekunde bearbeiten

Allen Inkompatibilitäten zum Trotz kann sich der Einsatz von HHVM durchaus lohnen. Die oben stehende Grafik zeigt die in einem Siege-Benchmark gemessenen maximalen Transaktionsraten bei 500 parallelen Nutzern.

Getestet wurde eine TYPO3-CMS-Site in Version 6.2 mit installiertem Introduction Package sowie eine TYPO3-Neos-Site in Version 1.0 mit installierter Demo-Site. Als Interpreter kamen PHP 5.5.3 (mit aktiviertem Opcache) sowie HHVM 3.0.1 zum Einsatz. Und als Webserver diente in beiden Fällen Nginx in Version 1.4.1. Deutlich zu sehen ist, dass ein HHVM-Server anwendungsunabhängig drei- bis viermal so viele Anfragen pro Sekunde bearbeiten kann wie ein ähnlich konfigurierter Server mit PHP-FPM.

Der Benchmark zur Verfügbarkeit verschiedener Server zeigt: PHP-FPM ist bereits bei einer vergleichsweise geringen Anzahl paralleler Zugriffe nicht mehr in der Lage, alle Anfragen zu beantworten. HHVM verhält sich hier deutlich stabiler.
Der Benchmark zur Verfügbarkeit verschiedener Server zeigt: PHP-FPM ist bereits bei einer vergleichsweise geringen Anzahl paralleler Zugriffe nicht mehr in der Lage, alle Anfragen zu beantworten. HHVM verhält sich hier deutlich stabiler.

Erste Schritte mit Hack

Neben der gesteigerten Performance unterstützt HHVM 3.0 auch den bereits erwähnten PHP-Dialekt Hack. Dieser erlaubt zusätzliche Features wie statische Typisierung, Collections und Generics. Das sieht dann zum Beispiel aus wie in Listing 4. Besonders zu beachten sind hier die geänderten Open-Tags (<?hh statt <?php) sowie die expliziten Typ-Hinweise für den Funktionsparameter und den Rückgabewert. Außerdem kommt mit dem Vector-Typ einer der neuen Collection-Typen zum Einsatz, der sich anstelle eines Arrays verwenden lässt.

Erweitertes „Hallo Welt“-Programm in Hack:

<?hh

function say_hello(Vector<string> $who) : int {
    $count = 0;
    foreach ($who as $name) {
   echo “Hello $who.\n”;
   $count ++;
 }
 return $count;
}

$names = Vector { “World”, “Universe” };
say_hello($names);

Listing 4

Ausblick

Mit der HipHop-Virtual-Machine hat Facebook eine ernstzunehmende Alternative zur herkömmlichen PHP-Laufzeitumgebung geschaffen. Zwar sind zahlreiche Anwendungen nur mit einigen Anpassungen unter der HHVM lauffähig, doch allein das deutlich bessere Laufzeitverhalten sollte Grund genug sein, das Projekt nicht aus den Augen zu verlieren.

Darüber hinaus ist die Kompatibilität zu PHP 5 (genauer gesagt: zu den populärsten Applikationen und Frameworks) eines der Entwicklungsziele von HHVM. Weiterhin entdecken zahlreiche PHP-Projekte HHVM als Laufzeitumgebung und optimieren ihren Code entsprechend. Man kann also davon ausgehen, dass sich künftig weitere PHP-Anwendungen problemlos mit HHVM nutzen lassen.

Martin Helmich
Martin Helmich

ist Softwarearchitekt beim Webhoster Mittwald und begeistert sich für aktuelle Themen der Software- und Web-Entwicklung. Außerdem ist er Mitverfasser der Bücher „Praxiswissen TYPO3“ und „Zukunftssichere TYPO3-Extensions mit Extbase & Fluid“, die beide im O'Reilly-Verlag erschienen sind.

Bitte beachte unsere Community-Richtlinien

2 Reaktionen
Oliver

....
echo “Hello $who.\n”; //ist falsch ;-)
echo “Hello $name.\n”; // sollte es wohl sein ;-)
....
:-D ist aber nicht so wild, ich denke jeder weiß was gemeint ist

Gruß

Niemand

Außerdem könnte man vielleicht noch schnell die Einrückung des Schnipsels verbessern ;).

Danke für den Artikel, wirklich informativ.
Leider kann ich das System noch nicht sinnvoll einsetzen, wegen der nicht 100% Kompatibilität zu PHP 5. Sollte es irgendwann so sein, müsste ich dann aber trotzdem noch jede Webseite durchtesten um zu sehen ob sie wirklich noch läuft.

Du musst angemeldet sein, um einen Kommentar schreiben zu können.

Jetzt anmelden