protofunc()

JS-Ladeperformance: Müßen wir die yslow-Regeln überdenken?

Tags: Performance, deutsch, javascript

Es gibt wohl auf der Welt keinen Frontend Entwickler, der nicht die wichtigsten Performance Regeln des Exceptional Performance teams von yahoo kennt.

Der wichtigste Teil dieser Regeln wurde 2006 erstellt und nicht nur Entwickler haben dazugelernt. Auch die Browser-Hersteller haben ihre Hausaufgaben gemacht und Performanceoptimierungen für die größten Ladebremsen durchgeführt. Einige dieser Browser-Optimierungen müßen zu einer Änderung der Regeln für Entwickler führen. Die bline Befolgung der Performance-Regeln führt zu einer ungerechtfertigten Bevorzugung des IE6 und des IE7 zu Lasten moderner Browser.

Put your JavaScript at the bottom

Die blinde Befolgung dieser Regel war mir schon immer ein Dorn im Auge. Wer sich die Ratio dieser Regel durchliest, könnte denken, daß Scripte, welche am Ende der Seite eingebunden sind, nicht mehr blockend laden. In Wirklichkeit blocken konventionell eingebundene Scripte immer, gleichgültig an welcher Stelle sie eingebunden wurden. Lediglich weil danach keine weiteren Resourcen kommen sollten, fällt dies nicht so gravierend auf. An der Gesamtladezeit einer Seite ändert sich hierdurch jedoch nichts. Lediglich die subjektive Ladezeit wird herabgesetzt, da der white page effekt dramatisch herabgesetzt wird, was wiederum immer zu Problemen von Flash of Unbehaviored Content und zumindest teilweise zu Flash of Unstyled Content führt.

Wer das blockende Laden lösen möchte, kann sein JS getrost im head dynamisch mit JS nachladen. Hierdurch wird das blockende Verhalten des JS ausgeschaltet, der Browser kann seine Downloads parallelisieren und auch die white page Zeit wird herabgesetzt. Da die JS-Dateien aber wesentlich früher geladen werden, treten die verschiedenen Arten von FOUCs seltener bis gar nicht auf.

Minimize HTTP Requests

Minimize HTTP Requests gehört wohl zu der goldenen Regel für die Frontend-Performance. Im Fall von JS wird empfohlen, alle Script-Dateien in eine einzelne Datei zu kombinieren. Diese Optimierung durch den Entwickler nimmt dem Browser jede Möglichkeit selbst Performance Optimierungen durchzuführen und ist in allen moderneren Browsern (inklusive IE8!) eine wahre Bremse.

Um diese Behauptung zu stützen, hier ein paar einfache Performancetests:

Ein erster Test mit cuzillion

ist ein nettes Tool um schnell mal ein paar Performance Tests durchzführen. Da die Mindestladezeit bei einer Sekunde liegt und keine CSS-Bilder simuliert werden können, sind die Ergebnisse jedoch immer mit Vorsicht zu genießen. Unser Cuzillion-Testaufbau, umfaßt immer 3 Stylesheets, 3 Bilder sowie ein iframe, welche je 1 Sekunde Ladezeit benötigen. Daneben wird JS von 2 Domains in unterschiedlicher Anzahl eingebunden, welche insgesamt 9 Sekunden betragen:

Wie schnell Laden nun die verschiedenen Browser die Seite, wenn wir diese JS-Dateien einerseits auf 2 Dateien und andererseits auf 8 Dateien zusammen fassen:

:
IE9: 10 | FF4: 10 | IE6: 15 | Chrome 11: 10

:
IE9: 5 | FF4: 4.6 | IE6: 16 | Chrome 11: 4.8

Wie wir sehen, wird die Seite durch Befolgung der Performanceregel im IE6 (und wohl auch im IE7) ein bißchen schneller, während dem die Seite in allen modernen Browsern deutlich langsamer wird.

Die Gründe für diese krassen Unterschiede sind relativ klar, moderne Browser haben mindestens 2 Performanceoptimierungen durchgeführt, welche durch das Zusammenfaßen von JS-Dateien nicht mehr ihre positiven Wirkungen entfalten können:

  • konventionell eingebundenes JS blockt nicht mehr
  • Die maximale Anzahl gleichzeitiger Requests zur gleichen domain wurden von 2 auf 4-8 angehoben

Ein weiterer nicht uninteressanter Test, ist das Laden von 8 JS Dateien, von denen 7 dynamisch eingebunden wurden:

:
IE9: 5 | FF4: 4.8 | IE6: 14 | Chrome: 5.5

Es zeigt sich, daß moderne Browser vom dynamischen Einbinden gar keinen Nutzen mehr ziehen können. Wirklich überraschend ist, daß der IE6 mit seinen beiden mageren Downloadslots die hohe Anzahl der Dateien durch Parallelisierung wettmachen kann.

Praxisnaher Performancetest

Als Grundlage für einen praxisnäheren Test diente ein Prototyp mit einer HTML Seite mit 60kb, unterschiedlicher Anazhl von JS-Dateien mit insgesamt 300kb, 4 x Stylesheet-Dateien (125kb), 25 x CSS-Bildern (140kb) und 5 x Inhaltsbildern (160kb). Für die weiteren Tests habe ich auf die alten Browser verzichtet und ausschließlich IE9 sowie FF4 verwendet, da beide mehr oder weniger gleich schnell sind, faße ich beide zusammen.

Auch habe ich mit verschiedenen Verbindungen getestet, da die Ergebnisse jedoch nicht relevant sind und nichts an der generellen Beobachtung ändern, bleiben die langsamen Verbindungsdaten unerwähnt.

Alle JS Dateien wurden grundsätzlich konventionell eingebunden.

Ladezeiten bei unterschiedlicher Anzahl von Dateien (Anzahl Dateien / DOM-Ready-Zeit / onload-Zeit):

  • 1 Dateien / 1100ms / 1600ms
  • 4 Dateien / 850ms / 1350ms
  • 6 Dateien / 800ms / 1300ms
  • 8 Dateien / 800ms / 1300ms
  • 12 Dateien / 800ms / 1300ms

Interessant an dem Ergebnis ist, daß sowohl IE9 als auch FF4 mit 6 Dateien ihr Performanceoptimum erreicht haben, aber andererseits durch Verdoppelung auf 12 Dateien keine Verlangsamung eintritt.

Wie aussagekräftig sind die Tests?

Um hier möglicher Kritik aus dem Weg zu gehen. Diese Ergebnisse beruhen auf ein paar kleinen Tests, welche mit Sicherheit nicht den Grundlagen der Statistik und des wissenschaftlichen Arbeitens folgen. Aber sie zeigen einen deutlichen Trend, der viele zum Umdenken/Neudenken befördern sollte.

Ähnliche Tests mit ähnlichen Ergebnissen wurden im Bereich der performanten Stylesheet-Einbindung bereits vor ein paar Jahren von Dirk Jesse gemacht, welcher eine Aufsplittung in 4 CSS-Dateien empfiehlt. (Ich habe aber wirklich echt nicht abgeschrieben).

Was bedeutet das für die Praxis?

Die Bedeutung von “Minimize http-requests” ist mit Sicherheit in der heutigen Browserlandschaft gesunken, hat aber immer noch Berechtigung. Der Entwickler muß sich hier darüber im Klaren sein, daß diese Regel der Parallelisierung von Downloads entgegensteht und einen angemessenen Ausgleich schaffen.

Dieser Ausgleich muß sich an den jeweiligen Größen der eingebundenen Dateien orientieren.

Das Verringern von http-requests einerseits dient vor allem der Reduzierung der Dauer für das Senden des Request-Headers sowie der Wartezeit bis der eigentliche Download beginnt, währenddem das “Auftrennen” von Dateien andererseits zu einer Reduzierung der eigentlichen Downloadzeiten durch Parallelisierung führt. Kurz: Ist eine Datei kleiner als 5kb sollte sie mit anderen zusammengefaßt werden, ist eine Datei dagegen größer 50kb sollte sie gesplittet werden.

Written March 1, 2011 by
protofunc