Verzögertes ready-Event durch JPGs via GZIP

Aus APF Wiki [de]
Wechseln zu: Navigation, Suche

Inhaltsverzeichnis

Einleitung

Ich habe in den letzten beiden Tagen einem Phenomen hinterher gejagt, das ich tatsächlich bisher noch nicht gesehen habe. Es lässt sich in diversen aktuellen Browsern reproduzieren (FF 3.6.X, Safari 4, ...) und da ich nach längerem Nachdenken die Lösung auch verstanden habe, wollte ich euch natürlich teilhaben lassen.

Anwendungsfall

Ich streame zur einfacheren Auslieferung von Modulen Bilder, die zu einem Modul gehören über eine Front-Controller-Action. Das hat den Vorteil, dass alle Bilder in einem Zip-Package zusammen mit dem Code ausgeliefert werden können und keine umständliche Installation von Code und Medien erfolgen muss. Die Action wird innerhalb einer Bootstrap-Datei ausgeführt, die den darin enthaltenen Code durch

ob_start('ob_gzhandler');
...
ob_end_flush();

einschließt. Die Action sendet die entsprechenden Header und streamt das Bild (oder auch CSS, JS, ...). Die Header sehen in exakt so aus:

Date    Wed, 13 Oct 2010 20:48:38 GMT
Server    Apache/2.0.63 (Win32) PHP/5.2.14
X-Powered-By    PHP/5.2.14
Content-Length    88285
Cache-Control    public; max-age=604800
Last-Modified    Wed, 13 Oct 2010 22:48:38 GMT
Expires    Wed, 20 Oct 2010 22:48:38 GMT
Content-Encoding    gzip
Vary    Accept-Encoding
Keep-Alive    timeout=15, max=100
Connection    Keep-Alive
Content-Type    image/jpg

Die Image-URL ist

http://***/Bildergalerie/***/~/3rdparty_imageresizer-action/showImage/image/advent08_1286992853/ext/jpg/path/GalleryMediaPath

Auswirkung

Bei der Anzeige der Bildergalerie wird die Seite mit seinen Inhalten schnell geladen. Das Bild, das über die FC-Action ausgeliefert wird, ebenfalls, jedoch dauert es dann im Durchschnitt 15s bis in der Seite das "document ready"-Event ausgelöst wird und der Browser signalisiert, die Seite sei komplett geladen.

Lösungsversuche

Setze ich statt JPG auf PNG, wird die Seite tadellos schnell geladen. Deaktiviere ich GZIP encoding, ist das "Problem" genauso schnell verschwunden, wie bei einem "Connection: close"-Header. Ich dachte zuerst noch daran, dass die per strlen() berechnete "Content-Length" falsch wäre, jedoch stimmt diese absolut mit der Datei-Größe überein.

Lösung

Problem bei der Auslieferung mit GZIP-Encoding und JPGs ist, dass JPGs fast nicht komprimierbar sind. Das bedeutet, dass der Browser das Bild schon vollständig innerhalb einer geringeren Daten-Menge erhält und damit wartet, dass die restlichen Daten "auch noch" ankommen. Ein eindeutiges Indiz dafür ist, dass ein "Connection: close"-Header dem Browser in der Lage ist mitzuteilen, dass der Datenstrom nun zu Ende ist (Holzhammer-Methode). Aus diesem Grund sollte man tunlichst keine "Content-Length"-Header senden, wenn man nicht tatsächlich weiß, welche Content-Länge ein gezipptes Objekt hat.

Meine Werkzeuge
Namensräume
Varianten
Aktionen
menü
misc
Werkzeuge