ob_gzhandler vs. zlib.output_compression

HTTP-Komprimierung beherrschen mittlerweile alle mehr oder weniger modernen Browser (ab IE 4). Es ist ein einfacher Weg die zu übertragende Datenmenge (Traffic) zu senken und dadurch auch den Seitenaufbau beim Besucher zu beschleunigen. Doch wie so oft führen mehrere Wege nach Rom, die gängigsten Varianten für die Einführung der Gzip-Komprimierung sind ob_gzhandler und zlib.output_compression. Dieser Beitrag beschreibt Vor- und Nachteile beider Varianten und gibt Tipps für den Einsatz.

Die Komprimierung von Textdaten mittels GZip bringt etwa 70% Einsparung in der zum Client zu übertragenden Datenmenge. Das Verfahren funktioniert dabei so:

  1. Client sendet Anfrage an Server und signalisiert, ob HTTP-Komprimierung unterstützt wird (Header-Feld Accept-Encoding)
  2. Erstellen und komprimieren des HTML-Codes (oder jeglichen anderen Codes vom MIME-Typ text) vom Server
  3. Übertragung des komprimierten Codes zum Client mit dem Hinweis, dass es sich um komprimierten Code handelt
  4. Dekomprimieren / Entpacken des Codes
  5. normale Verarbeitung des Codes, so als hätte es die Komprimierung nicht gegeben

Das Verfahren macht natürlich deutlich, dass der Vorteil der geringeren zu übertragenden Datenmenge nicht gratis daherkommt: Die Komprimierung der Daten auf dem Server kostet ein klein wenig Rechenkapazität, die es bei der direkten Ausgabe nicht gäbe. Man sollte deshalb ab und an mal auf die Prozessorauslastung schauen bzw. die Einstellung nicht aktivieren, wenn die Last auch so schon recht bzw. zu hoch ist.

ob_gzhandler
ob_gzhandler ist eine PHP-Callback-Funktion für ob_start, die die Ausgabe puffert und selbige nach Aufruf von ob_flush, ob_end_flush oder am Ende des Scripts per GZIP komprimiert und anschließend ausgibt. Das Sammeln (= Puffern) der einzelnen Ausgaben (echo bzw. print) hat den Vorteil, dass nicht jede einzelne Ausgabe sofort ausgeführt werden muss, sondern diese gesammelt und anschließend in größeren Paketen behandelt werden können. Diese Behandlung übernimmt dann die Funktion ob_gzhandler, indem sie die Ausgabe komprimiert (sofern der Client mit dem Accept-Encoding-Header signalisiert hat, dass er HTTP-Komprimierung beherrscht).

zlib.output_compression
zlib.output_compression ist eine Konfigurationsvariable, die in der php.ini aktiviert werden kann. Mit dieser Einstellung wird prinzipiell das gleiche gemacht wie von ob_gzhandler, allerdings muss man nicht jede PHP-Datei einzeln bearbeiten.

Vor- und Nachteile
Vorteile ob_gzhandler:

  • höhere Kontrolle, in welchen Dateien GZip-Komprimierung benutzt werden soll, falls dies nicht global für alle Dateien gewünscht wird
  • gezieltes Ausgeben / Leeren des Puffers (siehe unten)
  • kein Zugriff auf php.ini nötig (z.B. für Shared Hosting)

Vorteile zlib.output_compression:

  • zentrale Konfiguration -> es muss nicht jede PHP-Datei separat geändert werden

Es sei noch gesagt, dass beide Varianten voraussetzen, dass die zlib Extension auf dem Server installiert sein muss.
Außerdem ist darauf zu achten, dass man niemals nie beide Varianten gleichzeitig verwendet. Das endet in der Fehlermeldung

output handler ‚ob_gzhandler‘ conflicts with ‚zlib output compression‘

Ich persönlich bevorzuge die zlib.output_compression, da der PHP-Code unangetastet bleiben kann.
Ein Problem der oben beschriebenen Pufferung der Ausgabe ergibt sich insbesondere bei ob_gzhandler. Wer nämlich nur am Anfang der PHP-Datei einfach folgenden Code einfügt

ob_start("ob_gzhandler");

wird unter Umständen feststellen, dass der Seitenaufbau subjektiv langsamer wirkt. Das kommt daher, dass der Browser ohne HTTP-Compression sofort das versucht darzustellen, was er schon empfangen hat. Wenn nun das gesamte Dokument gepuffert wird, erhält der Browser die Ausgabe auch erst ganz am Ende „am Stück“. Das bedeutet, dass der Browser so lange warten muss bis das gesamte PHP-Script fertig ist. Bis dahin sieht der Besucher gar nichts.
Es ist deshalb notwendig, dass man vor eventuell langsamen Stellen (wie z.B. aufwändigen Datenbankabfragen) ein ob_flush() ausführt, sodass die bis dahin gepufferte Ausgabe erstmal zum Browser gesendet wird, damit der Besucher überhaupt etwas sieht.

zlib.output_compression umgeht dieses Problem, ist dabei aber nicht ganz so flexibel (aber weit weniger arbeitsintensiv). Hierbei kann die Puffergröße festgelegt werden (Standard 4 KB). Ist der Puffer voll, wird er an den Browser geschickt. Dadurch ist der Seitenaufbau für den Besucher deutlich flüssiger als mit ob_gzhandler allein. Oder anders gesagt: Es ist im Prinzip das gleiche als würde nach jeweils 4 KB ob_flush ausgeführt werden, nur dass man sich darum eben nicht kümmern muss.

Der Vollständigkeit halber sei noch gesagt, dass man sich auch eine eigene Callback-Funktion für ob_start schreiben kann. Darin könnte man dann den HTML-Code noch bearbeiten, indem z.B. alle Zeilenumbrüche entfernt werden. Hierbei muss nur darauf geachtet werden, dass das Accept-Encoding Header-Feld manuell geprüft wird und man je nach Wert gzencode oder gzdeflate anwendet. Außerdem müssen beim Output die Header-Felder Content-Encoding: gzip (bzw. deflate) und Vary: Accept-Encoding hinzugefügt werden.

Ich hoffe diese Ausführungen helfen euch weiter, denn durch HTTP Compression lässt sich die Ladezeit der Webseite recht einfach beschleunigen. Wie geht ihr in Richtung HTTP-Komprimierung vor? Nutzt ihr ob_gzhandler oder zlib.output_compression? Oder habt ihr eine eigene Callback-Funktion? Ich freue mich auf eure Kommentare.



Deprecated: Directive 'allow_url_include' is deprecated in Unknown on line 0