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.

Jan hat 152 Beiträge geschrieben

8 Kommentare zu “ob_gzhandler vs. zlib.output_compression

  1. Man kann natürlich auch den Apache die Arbeit machen lassen. Ich denke nicht, dass eine Komprimierung auf PHP-Seite noch was bringt, wenn man das DEFLATE-Modul, was ja genau das macht, im Apache laufen hat.

    Vorteil bei der Komprimierung im Apache: Auch statische Dateien (HTML, CSS, JS) werden zusammengepackt.

  2. Thomas sagt:

    Mich würde hierbei noch interessieren bei welchen Zugriffszahlen sich das ganze lohnt bzw. in welchen Szenarien. Schließlich geht es ja hierbei um Netzwerklast vs. Serverlast. Ab wann ist der Server durchs viele Komprimieren langsamer als der Vorteil, den man beim Netzwerktransfer daraus zieht?

    Liebe Grüße, Thomas

  3. bmueller sagt:

    Ich verwende ausschließlich die Komprimierung über Apache, mit dem man ja auch statische Text Dateien (CSS, JS) komprimieren kann. Dazu noch das ganze mit mod_expire gekoppelt und der Traffik ist fast auf null.

    Zur “Netzwerklast vs. Serverlast”:
    Egal ob kleine oder große seite es lohnt sich! Man sollte nur das Kompressionslevel nicht zu hoch einstellen, im grunde liegt es nur daran dort das richtige Level zu finden.

    Bis jetzt gab es bei meien Projekten noch keine Negativen erscheinungen seit der Komprimierung nur positive, wie Traffik einsparung von rund 70% und nem schnelleren seiten aufbau.

    Bilder sollt man hingegen nicht Komprimieren das diese meinst schon Komprimiert sind oder die last zu groß wird für den Server.

  4. Thomas W sagt:

    Ich setze auch hauptsächlich Kompression über mod_deflate ein. Bei Seiten, die hohen Traffic hat, bringt das enorm viel. Eine weitere Möglichkeit, die Last des Apache selbst zu verringern, ist der Einsatz von varnishd.

  5. PHP Ratte sagt:

    Sehr hilfreich!

    Ich bin erst vor kurzem zufällig auf gzip Komprimierung gestoßen und verwende seit dem ob_start(“ob_gzhandler”);. Du hast mich überzeugt das zlib.output_compression: besser ist nur leider habe ich keinen Zugriff auf die php.ini.

    Eine Sache werde ich aber ändern. Ich benutze ab und zu ob_flush gerade weil meine Datein bis zu 100kb groß sind.

    Nochmal Danke!

    Gruß

  6. Torsten sagt:

    Du hast die Vor- und Nachteile von ob_gzip gut ausgefuehrt. So klar hab ich das noch nirgendwo anders gelesen. Einige Kommentare hier haben mir auch einen besseren Einblick verschafft. Ich beschaeftige mich mit dem Thema Performance (PHP, SQL, JS) intensiv seitdem ich die Idee hatte, eine Community Platform fuer Offroad Fahrzeuge aufzubauen. Schneller Seitenaufbau und geringe Netzwerklast waren dabei von Anfang an auf meiner ToDo-Liste. Ich denke hier kann ich noch viel tun. Danke fuer deinen Blog, ich wuenschte nur, ich haette den schon eher gefunden. 😉

Eine Antwort schreiben

Ihre E-Mail-Adresse wird nicht veröffentlicht. Benötigte Felder sind markiert mit *

You may use these HTML tags and attributes: <a href=""> <blockquote cite=""> <pre lang=""> <b> <strong> <i> <em>