php.de

Zurück   php.de > Webentwicklung > PHP-Fortgeschrittene

PHP-Fortgeschrittene Arbeiten mit PHP ohne Einschränkungen

Antwort
 
LinkBack Themen-Optionen Thema bewerten
Alt 13.10.2010, 22:09  
Moderator und Wett-König
 
Benutzerbild von dr.e.
 
Registriert seit: 21.05.2008
Beiträge: 3.657
PHP-Kenntnisse:
Fortgeschritten
dr.e. ist ein Lichtblickdr.e. ist ein Lichtblickdr.e. ist ein Lichtblickdr.e. ist ein Lichtblickdr.e. ist ein Lichtblickdr.e. ist ein Lichtblick
dr.e. eine Nachricht über Skype™ schicken
Standard Verzögertes "document ready"-Event durch JPGs via GZIP

Hallo zusammen,

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

PHP-Code:
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:

Code:
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

Code:
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.

Happy GZIP'in,
Dr.E.
__________________
Viele Grüße,
Dr.E.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1. Think about software design before you start to write code!
2. Discuss and review it together with experts!
3. Choose good tools (-> Adventure PHP Framework (APF))!
4. Write clean and reusable software only!
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
dr.e. ist offline   Mit Zitat antworten
Sponsor Mitteilung
PHP Code Flüsterer

Registriert seit: 21.08.2005
Beiträge: 4682
PHP-Kenntnisse:
Fortgeschritten

Alt 13.10.2010, 22:30  
Moderator
 
Benutzerbild von Chriz
 
Registriert seit: 11.05.2008
Beiträge: 6.267
Chriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer Anblick
Standard

Dieses Warten auf restliche Daten bei falscher Content-Length/Komprimierung hatte ich auch schon. Wenn der Apache die Kompression übernimmt gehts, über PHPs ob_start/gzhandler hatte ich das selbe Problem.
__________________
"Nuschel ich?" - "Was?"
Chriz ist gerade online   Mit Zitat antworten
Alt 13.10.2010, 22:44  
Moderator¹
 
Registriert seit: 28.03.2010
Beiträge: 7.470
PHP-Kenntnisse:
Fortgeschritten
ChrisB ist ein wunderbarer AnblickChrisB ist ein wunderbarer AnblickChrisB ist ein wunderbarer AnblickChrisB ist ein wunderbarer AnblickChrisB ist ein wunderbarer AnblickChrisB ist ein wunderbarer AnblickChrisB ist ein wunderbarer Anblick
Standard

Zitat:
Zitat von dr.e. Beitrag anzeigen
Lösung: Problem bei der Auslieferung mit GZIP-Encoding und JPGs ist, dass JPGs fast nicht komprimierbar sind.
Logisch, weil die gleichen Komprimierungsalgorithmen innerhalb des JPG schon zur Anwendung kommen.

Zitat:
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.
Hier komme ich nicht mehr so ganz mit ... war jetzt die angegebene Content-Length in Bezug auf die GZIP-kodierten Daten falsch, und sie zu korrigieren behebt das Problem?

Falls nicht, sehe ich nicht, was für einen Unterschied es nun machen soll, ob sich der jeweilige Datentyp mehr oder weniger stark komprimieren lässt.
__________________
RGB is totally confusing - I mean, at least #C0FFEE should be brown, right?
ChrisB ist offline   Mit Zitat antworten
Alt 14.10.2010, 08:37  
Erfahrener Benutzer
 
Registriert seit: 01.09.2010
Beiträge: 4.561
PHP-Kenntnisse:
Fortgeschritten
eagle275 ist ein sehr geschätzer Menscheagle275 ist ein sehr geschätzer Menscheagle275 ist ein sehr geschätzer Mensch
Standard

hab ich jetzt auch so verstanden, dass du die Content-Length der unkomprimierten Daten geliefert hast - aber Gerade dann sollte JPEG kein Problem haben, weil dort ja quasi 1:1 rauskommt bzw. die Datei eher wieder ein paar Byte größer wird

oder wolltest du die "Holzhammer"-Methode als Lösung propagieren ?
eagle275 ist offline   Mit Zitat antworten
Alt 14.10.2010, 12:00  
Moderator und Wett-König
 
Benutzerbild von dr.e.
 
Registriert seit: 21.05.2008
Beiträge: 3.657
PHP-Kenntnisse:
Fortgeschritten
dr.e. ist ein Lichtblickdr.e. ist ein Lichtblickdr.e. ist ein Lichtblickdr.e. ist ein Lichtblickdr.e. ist ein Lichtblickdr.e. ist ein Lichtblick
dr.e. eine Nachricht über Skype™ schicken
Standard

Zitat:
Hier komme ich nicht mehr so ganz mit ... war jetzt die angegebene Content-Length in Bezug auf die GZIP-kodierten Daten falsch, und sie zu korrigieren behebt das Problem?

Falls nicht, sehe ich nicht, was für einen Unterschied es nun machen soll, ob sich der jeweilige Datentyp mehr oder weniger stark komprimieren lässt.
Die Content-Length kann ich in diesem Konstrukt nicht korrigiert haben, da sie von PHP-OB-Mechanismen nachträglich beeinflusst wird. Der Witz ist eben genau, dass sich JPEG-Dateien fast nicht komprimieren lassen. Die ganze Zeit war ich der Meinung war, dass das deshalb hinsichtlich der Content-Length transparent ist und habe deshalb den auf den unkomprimierten Datenstrom berechnete Wert für korrekt befunden.

Zitat:
hab ich jetzt auch so verstanden, dass du die Content-Length der unkomprimierten Daten geliefert hast - aber Gerade dann sollte JPEG kein Problem haben, weil dort ja quasi 1:1 rauskommt bzw. die Datei eher wieder ein paar Byte größer wird
Das dachte ich auch, ist aber nicht so und fällt besonders bei großen Bildern ins Gewicht.

Zitat:
oder wolltest du die "Holzhammer"-Methode als Lösung propagieren ?
Keinesfalls! Das ist hinsichtlich des connection sharing/pooling des Browsers glatter Blödsinn, denn dann wird die Zeit für das Nachladen von Bildern künstlich verlängert. Und das wollen wir doch nicht.
__________________
Viele Grüße,
Dr.E.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1. Think about software design before you start to write code!
2. Discuss and review it together with experts!
3. Choose good tools (-> Adventure PHP Framework (APF))!
4. Write clean and reusable software only!
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
dr.e. ist offline   Mit Zitat antworten
Alt 14.10.2010, 20:22  
hts
Erfahrener Benutzer
 
Registriert seit: 07.09.2010
Beiträge: 722
PHP-Kenntnisse:
Fortgeschritten
hts befindet sich auf einem aufstrebenden Ast
Standard

Also lieferst du jetzt ohne Content-Length-Header aus?

Habe hier gerade etwas gefunden (geschachtelte OB-Buffer): http://stackoverflow.com/questions/8...a-gzipped-file

PHP-Code:
// Start buffered output 
ob_start(); 
// Check for gzip capability 
if (stripos($_SERVER['HTTP_ACCEPT_ENCODING'], "gzip") !== false) { 
  
ob_start("ob_gzhandler"); 
  echo 
file_get_contents($filename); 
  
ob_end_flush(); 
} else 
  echo 
file_get_contents($filename); 
 
// Write the content length 
header('Content-Length: '.ob_get_length()); 
ob_end_flush(); 
hts ist offline   Mit Zitat antworten
Alt 14.10.2010, 21:22  
Moderator und Wett-König
 
Benutzerbild von dr.e.
 
Registriert seit: 21.05.2008
Beiträge: 3.657
PHP-Kenntnisse:
Fortgeschritten
dr.e. ist ein Lichtblickdr.e. ist ein Lichtblickdr.e. ist ein Lichtblickdr.e. ist ein Lichtblickdr.e. ist ein Lichtblickdr.e. ist ein Lichtblick
dr.e. eine Nachricht über Skype™ schicken
Standard

Hallo hts,

Zitat:
Also lieferst du jetzt ohne Content-Length-Header aus?
Korrekt. Gemäß HTTP-Protokoll ist das auch erlaubt (siehe RFC-2616):

Code:
     3.If a Content-Length header field (section 14.13) is present, its
     decimal value in OCTETs represents both the entity-length and the
     transfer-length. The Content-Length header field MUST NOT be sent
     if these two lengths are different (i.e., if a Transfer-Encoding
     header field is present). If a message is received with both a
     Transfer-Encoding header field and a Content-Length header field,
     the latter MUST be ignored.
Der Link ist jedoch interessant, die Funktion kannte ich noch nicht.
__________________
Viele Grüße,
Dr.E.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1. Think about software design before you start to write code!
2. Discuss and review it together with experts!
3. Choose good tools (-> Adventure PHP Framework (APF))!
4. Write clean and reusable software only!
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
dr.e. ist offline   Mit Zitat antworten
Alt 14.10.2010, 21:31  
hts
Erfahrener Benutzer
 
Registriert seit: 07.09.2010
Beiträge: 722
PHP-Kenntnisse:
Fortgeschritten
hts befindet sich auf einem aufstrebenden Ast
Standard

Zitat:
Zitat von dr.e. Beitrag anzeigen
Korrekt. Gemäß HTTP-Protokoll ist das auch erlaubt (siehe RFC-2616)
Ja, hatte ich mir schon vorab angesehen.

http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html unter "14.13 Content-Length"

Zitat:
The Content-Length entity-header field indicates the size of the entity-body, in decimal number of OCTETs, sent to the recipient or, in the case of the HEAD method, the size of the entity-body that would have been sent had the request been a GET.

Content-Length = "Content-Length" ":" 1*DIGIT
An example is

Content-Length: 3495
Applications SHOULD use this field to indicate the transfer-length of the message-body, unless this is prohibited by the rules in section 4.4.

Any Content-Length greater than or equal to zero is a valid value. Section 4.4 describes how to determine the length of a message-body if a Content-Length is not given.

Note that the meaning of this field is significantly different from the corresponding definition in MIME, where it is an optional field used within the "message/external-body" content-type. In HTTP, it SHOULD be sent whenever the message's length can be determined prior to being transferred, unless this is prohibited by the rules in section 4.4.
Und da SHOULD immer in Großbuchstaben geschrieben ist, klingt das nach einer sehr starken Empfehlung, wenn auch kein muss
hts ist offline   Mit Zitat antworten
Alt 14.10.2010, 22:39  
Moderator und Wett-König
 
Benutzerbild von dr.e.
 
Registriert seit: 21.05.2008
Beiträge: 3.657
PHP-Kenntnisse:
Fortgeschritten
dr.e. ist ein Lichtblickdr.e. ist ein Lichtblickdr.e. ist ein Lichtblickdr.e. ist ein Lichtblickdr.e. ist ein Lichtblickdr.e. ist ein Lichtblick
dr.e. eine Nachricht über Skype™ schicken
Standard

Danke für das Zitat, ich kenne das RFC zur Genüge! Ich werde aber bei Gelegenheit den Tipp mit ob_get_length() testen.

Update: der Einbau des Snippets am Ende der index.php bringt nicht den gewünschten Erfolg. Der Header wird auch mit explizitem Replace-Flag nicht gesendet. Ich werd das bei Gelegenheit mal analysieren.
__________________
Viele Grüße,
Dr.E.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1. Think about software design before you start to write code!
2. Discuss and review it together with experts!
3. Choose good tools (-> Adventure PHP Framework (APF))!
4. Write clean and reusable software only!
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Geändert von dr.e. (15.10.2010 um 09:39 Uhr).
dr.e. ist offline   Mit Zitat antworten
Antwort


Themen-Optionen
Thema bewerten
Thema bewerten:

Forumregeln
Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are an
Gehe zu

Besucher kamen über folgende Suchanfragen bei Google auf diese Seite
ready event, ready event geladen, html document ready event, document.ready bilder, dom ready event, ready event geladen?, was ist ready event, on document ready event, document.ready() auslösen, document ready bilder, document.ready auslösen, document ready ereignis auslösen, (document).ready bilder, $(document).ready, gzip php 5.2, document.ready senden, document ready event, gzip jpegs, zeit bis document.ready, document ready

Alle Zeitangaben in WEZ +2. Es ist jetzt 22:36 Uhr.




Powered by vBulletin® Version 3.7.2 (Deutsch)
Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.2.0
Aprilia-Forum, Aquaristik-Forum, Liebeskummer-Forum, Zierfisch-Forum, Geizkragen-Forum