Donnerstag, 21. März 2013

Nutzen der Browser Download-Parallelisierung für schnellere Websites

In einigen früheren Posts habe ich angesprochen, dass ein Browser nur z.B. 6 Ressourcen gleichzeitig downloaden kann, und die nächsten 6 dann in einem zweiten, dritten, vierten Schritt herunterlädt. Moderne Websites brauchen oft gegen 50-60 Ressourcen (Bilder, Javascript, CSS), was dann die Website im ersten Aufruf langsam erscheinen lässt, da es 10 hintereinander liegende Download Durchgänge braucht.

Dies resultiert darin, dass eine Website im blödsten Falle blockiert bis alle Ressourcen gedownloadet wurden, oder dass die Seite progressiv aufgebaut wird - was je nach Anwendung störend sein kann.

In diesem Artikel beschreibe ich, wie man mit dieser Limitation um gehen kann.

Wieso limitiert ein Browser die Download-Warteschlangenlänge?

Der HTTP 1.1 Standard in der RFC 2616 Kapitel 8.1.4 beschreibt, dass ein Browser maximal 2 Ressourcen gleichzeitig vom gleichen Host anfordern sollte. Mittlerweile downloaden die meisten modernen Browser entgegen dem Standard 6-8 Ressourcen gleichzeitig. Doch wieso überhaupt diese Limite?

Die RFC wurde zu Zeiten geschrieben, als das Web noch langsam, die Bandbreiten limitiert und die Server für heutige Verhältnisse absolut unperformant waren. Die Limite dient zum Schutz von Webservern vor Überlastung. Die Limiten wurden heute in den Browsern erhöht, doch sind sie noch da. Ja, das Web ist schneller, die Server performanter... aber die Websites viel umfangreicher!

Parallelisierung von Downloads über verschiedene Hosts

Hat man nun eine Website, die aus diversen Ressourcen (z.B. vielen Bildern) besteht, so ist der einfachste Trick der, dass man die Ressourcen über verschiedene Domain Namen verteilt. Dabei müssen die Domains nicht mal auf verschiedenen Hosts liegen - es reicht bereits aus, wenn es sich um Domain Aliase handelt, die sich im gleichen Hosting auf dem gleichen Server befinden.

Beispiel Google Maps

Im nachfolgenden Beispiel werden von Google Maps diverse Kacheln für die "Satelliten-Ansicht" geladen. Dies sind weitaus mehr als 6 Stück, und sie werden über diverse Domain-Aliase verteilt; laden damit also alle gleichzeitig:


Das gleichzeitige Laden ist nötig, damit die Karte sofort erscheint, und nicht zeilenweise aufgebaut werden muss. Im Screenshot sind in der ersten spalte die verschiedenen Domain Aliase ersichtlich, und ganz rechts die Startzeitpunkte der Downloads.

Falltüren

  • Kann der Host so viele gleichzeitige Requests auch handhaben?
  • Wie viel Zeit braucht ein DNS Lookup, um den Domain-Namen in eine IP-Adresse umzuwandeln?
Die erste Frage zu beantworten bedürfte einen neuen Post (Ideen für neue Posts sind immer willkommen!). Beim Apache ist die Frage zum Beispiel mit der Anzahl Sub-Prozessen des Servers beantwortbar. Hier muss man einfach etwas abwägen und ausprobieren.

Die zweite Frage zumindest kann mit Messungen beantwortet werden. Ein DNS Lookup braucht einige Milisekunden Zeit, und wird durch eine Round-Trip-Time verzögert. Allerdings muss ein Lookup nur einmal gemacht werden, danach wird das Resultat vom Browser, vom Betriebsystem und schlussendlich vom lokalen DNS Server zwischengespeichert. Hier kann man nur Erfahrungswerte nennen: Aus eigener Erfahrung holt man das Optimum bei vielen Ressourcen über 3 bis maximal 5 Domain Aliase heraus.

Wann lohnt sich die Technik der DNS Aliase?

Bei Websites mit weniger als 10-20 Ressourcen Anforderungen würde ich empfehlen, gar nichts zu unternehmen. Danach sollte man anfangen, in Sechser-Schritte die Ressourcen auszulagern, also etwa so:
  • Alle CSS-Files (z.B. 5 Stück) auf static01.insor.ch
  • JavaScript-Files (z.B. 15 Stück)
    • 6 auf static01.insor.ch
    • 6 auf static02.insor.ch
    • 3 auf static01.insor.ch
  • Alle Bilder (z.B. 30 Stück)
    • 6 auf static02.insor.ch
    • 6 auf static03.insor.ch
    • usw.
Wichtig ist dabei auch, die Ladereihenfolge der CSS- und Javascript Files zu beachten, und die Javascripts allenfalls mit dem Script Attribut "async" zu laden. Danach muss man sich überlegen, in welcher Reihenfolge die Bilder geholt werden, und welcher Domainname zum entsprechenden Zeitpunkt wohl am "wenigsten ausgelastet" sein dürfte - und so sind die Files zu verteilen.

Zu beachten ist, dass die Files aber immer von der selben Domain aus angeboten werden - so können wir die Browser-Caching-Mechanismen benutzen. Würden die CSS-Dateien plötzlich von einer anderen Domain referenziert werden, müsste der Browser alles erneut downloaden.

Schlussendlich kommt man nicht darum herum, die Sache mit FireBug oder ähnlichem Tool einfach mal zu testen und etwas rum zu spielen, bis man das Optimum heraus geholt hat.

Und sonst...?

Bei grossen Ressourcen spielt dann bald auch mal die Bandbreite eine Rolle. Hier könnte man sich überlegen, die Ressourcen auf ein Content Delivery Network auszulagern. Die meisten CDN unterstützen zudem das Anbieten der Ressourcen über verschiedene Domain Aliase.

Feedback

Habt ihr Erfahrungen mit dieser Optimierungstechnik gemacht? Bitte kommentiert doch mit der entsprechenden Kommentarfunktion unten. Ich bin auch immer offen für Anregungen für neue Themen!

Donnerstag, 14. März 2013

Minimieren von HTTP Requests: Single CSS/JS und Sprites

In meinem letzten Artikel über das Verteilen von Ressourcen auf Content Delivery Networks habe ich das Thema schon angeschnitten, dass man die Anzahl HTTP Requests minimieren sollte, um den Multiplikator der Round-Trip-Time gering zu halten. Nun erkläre ich, wie man das Maximum herausholt, indem man Ressourcen zusammenfasst.

Was ist das Problem bei Anforderung zahlreicher Ressourcen?

Die allermeisten Websites laden mehrere CSS und mehrere Javascript Dateien - gerade bei letzteren für einzelne Module der Übersichtlichkeit halber über diverseste Files. Der HTTP 1.1 Standard empfiehlt, dass ein Browser maximal 2 Ressourcen parallel von einem Host anfordert - die meisten Browser fordern zwar mehr an (ca. 6), aber das Problem ist dasselbe: Sind Javascripts über 24 Files verstreut, kann ein Browser diese maximal in einer Sechser-Parallelisierung downloaden - in unserem Fall wären das 4 mal hintereinander 6 parallele Downloads. Folgendes Netzwerk-Audit einer Website mit 20 Javascript Referenzierungen im Source (insgesamt 197 angeforderte Ressourcen)  illustriert dies, man beachte im Tooltip den Wert unter "Blocking" (damit ist gemeint, dass der Browser so lange blockiert war, bis er den Download resp. die Verarbeitung einleiten konnte):


Zum Zeitpunkt der Anforderung dieser Ressource, verbrachte der Browser also rund eine halbe Sekunde nur mit blockierendem Warten.

In meinem Artikel über den Einsatz von Content Delivery Netzwerken (CDN) habe ich berichtet, dass wir dies entschärfen könnten, indem wir diese Ressourcen auf einen anderen Host legen - denn die Limite von 6 parallelen Download bei modernen Browsern gilt per Host.

In einem anderen Artikel von mir habe ich zudem den Einsatz von Cache-Control-Headers empfohlen, womit die Ressourcen nach dem ersten Download im Browser-Cache verbleiben und so nicht jedes Mal neu angefordert werden müssen.

Tipp 1: Zusammenfassen von CSS

Dies ist wohl die einfachste Möglichkeit: CSS wird sequentiell abgearbeitet, also würde es reichen, die CSS Dateien in der richtigen Reihenfolge einfach in eine einzige Datei zusammenzufügen. Damit haben wir nur noch eine CSS Datei, und brauchen damit auch nur einen Request zu machen. 

Es kommt natürlich oft vor, dass gewisse CSS Dateien nur für einzelne Seiten gelten - diese kann man aber auch einzeln belassen. Das Ziel ist einfach, nicht unnötig viele Dateien zu haben. Also weg vom "modularisierten" Denken, wenn es um Performance geht!

Wem dies zu unübersichtlich wird, der kann auch ein kleines Script schreiben, welches ihm die CSS Dateien zusammenfasst und als gecachte Datei auf dem Webserver ablegt. Dies liesse sich soweit automatisieren, dass wenn das Datum der Source Dateien ändert, das Script bei einer neuen Anforderung ein neues Master-CSS generiert und ausliefert. Der Scripting Overhead und die mittlere Filesystemzugriffszeit von einigen Milisekunden machen sich bezahlt, verglichen mit der enormen Zeit für mehrere Round-Trips (vor allem wenn es mehr als 6 sind).

Tipp 2: Zusammenfassen von Javascript

Auch JavaScripts werden sequentiell abgearbeitet, also lassen sich auch diese in einer einzelnen Datei zusammenfassen - nach dem gleichen Prinzip wie bei den CSS Dateien. Ein Paradebeispiel ist jQuery, welches aus einem Master-JavaScript, und für jedes Modul aus einem weiteren CSS-Script besteht. Eine aufwändig interaktive Website wird schnell mal 10-20 solche Module laden, und das sind einfach wieder 4 Round-Trips à 6 parallelen Downloads.

Tipp 3: Arbeiten mit CSS-Sprites

Dabei packen wir das letzte Problem beim Kragen, und das sind übermässig viele Bilder, die einzeln mit HTTP-Requests vom Webserver angefordert werden. Auch hier gilt die Limite von 2 parallelen Downloads gemäss HTTP 1.1 Spezifikation. Was wir tun können ist folgendes: Anstatt 20 kleine Bilder zu erstellen (z.B. Runde Ecken, Buttons, usw.) - erstellen wir ein einzelnes, sehr breites Bild, in welchem alle diese Elemente enthalten sind. Danach positionieren wir die Bilder mit den CSS-Direktiven "background-image" und "background-position", so dass in einem DIV nur jener Ausschnitt des Bildes angezeigt wird, der für das DIV (z.B. eine Schaltfläche) auch interessant ist.

Damit reduzieren wir die Anzahl Requests für 20 Bilder auf einen. Dieser Tipp funktioniert natürlich nur mit Bildern, die wir effektiv per CSS verwenden. Werden die meisten Bilder mit <img> Tags geladen, würde die Umsetzung dieser Strategie zu einem Reeingineering des Web Templates führen. Ob dies den Aufwand rechtfertigt, ist im Einzelfalle abzuklären.

Ein gutes Beispiel für die CSS Sprite Technik sind zum Beispiel Landesflaggen. Anstatt 265 Requests vom Webserver anzufordern, holt man sich das Sprite mit einem einzigen Request. Die Ladeperformance ist definitiv spürbar!

Tipp 4: Minifizieren (verkleinern) von CSS und JS

Es existieren diverse Tools (wie z.B. der YUI Compressor), die aus CSS und Javascripts Leerzeilen, Abstände und Kommentare rausnehmen, um die Grösse der Dateien zu reduzieren. Bei Javascript werden selbst Funktions- und Variablennamen auf ein Minimum abgekürzt. Natürlich ist der Code danach nicht mehr leserlich. Der Hintergedanke ist aber auch, dass man dies nur für die endgültige Version macht, die dann auch bereitgestellt wird. Dies liesse sich mit unter Tipp-1 genanntem Script ebenfalls automatisieren, was ich aber nicht empfehle. Eine minimierte Version eines CSS/JS will trotzdem noch getestet sein.

Bei eingeschalteter serverseitigen Komprimierung ist die Minifizierung fast ohne Gewinn; man holt durch die fehlenden Kommentare usw. in der Regel kaum viel mehr als weitere 5% heraus.

Fazit

Würde man es schaffen, dass eine Website nur aus einem HTML-, einem CSS- und einem Javascript Dokument besteht; und würde man die Bilder mittels der CSS-Sprites Techniken in nur ein Bild packen, so würde die Website mit einem modernen Browser sämtliche Ressourcen im ersten und einzigen Durchgang downloaden können. Während die CSS-Sprite-Technik aufwändig umzusetzen ist, so ist das Zusammenfassen von JS und CSS aber sicher ein kleiner Aufwand. 

Eine umfassende Websites mit 30 CSS und JS Dateien (gerade bei JS Libraries), und einer RTT von 50ms, spart sich damit 200ms an blockierender Wartezeit durch Parallelitätslimitierungen. Kommt ein Besucher aus Übersee, fällt die RTT hier massiver ins Gewicht. Extrem wird es bei Nutzern von mobilen Endgeräten, wo die RTT in der Regel über 200ms liegt. Auf der Strecke Zürich-Bern mit den schweizerischen Bundesbahnen habe ich nicht selten eine RTT von 2000ms über 3G-Netzwerke. Was das für das Laden von 265 Flaggen bedeutet, liegt auf der Hand.

Samstag, 9. März 2013

Speed und Ausfallssicherheit durch Content Delivery Networks (CDN)

In meinem letzten Artikel über die Ladereihenfolge von CSS und JS Dateien habe ich berichtet, dass man damit die Parallelität der Downloads positiv beeinflussen kann, wenn man dabei einige Grundregeln beachtet. Nun gehe ich einen Schritt weiter und zeige, wie man diese Ressourcen auf CDN's verteilt und damit noch höhere Performance rausholen kann.

Dieser Artikel ist vor allem interessant für Betreiber trafficstarker Websites.

Was sind Content Delivery Networks (CDN)?

Dabei handelt es sich um grosse Provider wie Akamai, Amazon, CloudLayer, usw. Diese fungieren als Reverse-Proxies für bestehende Websites, können aber auch verwendet werden, um häufig gebrauchte Ressourcen auszulagern und somit den "kleinen, lokalen" Hostinganbieter zu entlasten. Wieso würde man dies wollen?
  1. Shared-Hosting: Dabei teilt man sich den Webspace mit anderen. Entsteht eine Last auf einer Website eines anderen Kunden, wird die eigene Website ebenfalls runtergezogen, das Laden von einzelnen Ressourcen zieht sich hin, und dies beeinflusst die Gesamtladezeit der Website negativ.
  2. Traffic-Limiten: Bei den meisten Hostinganbietern ist nach einem Terabyte Schluss, oder es fallen vergleichsweise hohe Gebühren an
  3. Bandbreiten-Limitierung: Die meisten Hosting-Anbieter drosseln die Bandbreite pro (dedizierten) Server auf 100mbit/s (Stand Januar 2013). Finden durch verschiedene User nun Streamings von Videos, oder Downloads statt, bleibt keine Bandbreite mehr für das Laden der Page
  4. Traffic-Burst: Gerade bei Werbekampagnen kann es gut sein, dass ein Peak entsteht, welcher der Hostingserver nicht zu verarbeiten vermag. Das Resultat sind enorm degradierte Ladezeiten oder Totalausfälle.
Auf den vierten Punkt gehe ich in diesem Artikel nicht ein, dies ist ein anderes Thema. Dies wird in der Regel ebenfalls mit dem Einsatz von CDN gelöst.

Wie sind CDN aufgebaut?

Vereinfacht gesagt, sind dies Storage- und Netzwerkprovider. Ihr ladet eine Ressource hoch, und kriegt hierfür eine Zugriffs-URL. Der CDN Provider unterhält weltweit diverse synchronisierte Datacenters, und die angeforderten Ressourcen werden immer von demjenigen Rechenzentrum geladen, welches sich am Nächsten zum aufrufenden User befindet. Ein User in China wird also die Ressource aus einem Rechenzentrum in China abrufen; ein User aus Deutschland dann z.B. aus einem Rechenzentrum in Irland.

Diese CDN Anbieter verrechnen dabei den verwendeten Storage, den verwendeten Traffic und die bedienten HTTP Requests (als Beispiel, die Verrechnungsmodelle sind vielfältig).

Umsetzung

Diverse Ressourcen einer Website sind statisch (vor allem grosse Banner-Bilder, aber auch CSS, JavaScript, usw.). Anstatt sich hier nun auf eher langsame Leitungen oder Server zu verlassen, könnte man diese Ressourcen auf ein CDN auslagern. Das Vorgehen ist dabei wie folgt:
  1. Anmeldung bei einem CDN
  2. Upload der Ressourcen, respektive Sync der gesamten Website mit dem CDN
  3. Lösen eines Domainnames, damit auf die Ressourcen des CDN zugegriffen werden kann (in der Regel  wird einem eine solche URL mitgeteilt)
  4. Ersetzen der lokalen Referenzierung von Ressourcen (js, css, img) in den HTML Sourcen mit externen Referenzierungen auf das CDN

Was erreicht man damit?

Zu beobachten sind zwei Haupteffekte:
  1. Erhöhung der Parallelisierung der Ressourcen-Downloads: Ein Browser lädt in der Regel 6 Ressourcen gleichzeitig vom selben Host herunter, dann die nächsten 6, usw. Durch die Verwendung von CDN kommen diese Ressourcen von einem anderen Ort, werden also parallel zu allen anderen lokalen Ressourcen heruntergeladen. Der Geschwindigkeitszuwachs dürfte vor allem bei Bannerbilder usw. spürbar sein.
  2. Tiefere Round-Trip-Times bei ausländischen Besuchern: Ein Besucher aus den Staaten hat eine relativ hohe Latenzzeit zwischen Anfrage und Antwort vom Server - dies ist rein physisch durch die Distanz bedingt. Dadurch, dass die Ressourcen von einem für den User lokalen CDN-Mirror geholt werden, verringert sich die RTT auf ein Minimum, was absolut spürbar ist. Beispiel: Zwischen London und New York beträgt die RTT auf neuesten Leitungen ca. 60ms. Das ist reine Wartezeit bedingt durch die Distanz. Werden diverse Ressourcen sequentiell geladen (z.B. Javascripts), summiert sich diese Zahl entsprechend schnell auf.
  3. Erhöhte Bandbreite, womit die Ressourcen schneller heruntergeladen werden
Weitere positive Nebeneffekte:
  1. Die CDN übernehmen das Cache-Controlling. Wer dies also nicht selber machen kann (siehe mein Artikel über Cache-Control-Headers), der muss sich beim Einsatz von CDN nicht mehr darum kümmern.

Einrichtung und Kosten?

Die Sache ist einfacher als man denkt. Angemeldet hat man sich bei einem CDN schnell, und das syncen einer Website hat man auch innert meist nützlicher Frist hinter sich.

Die Kosten fallen wie folgt an (Beispiel Amazon CloudFront, Preise Europa und USA, Stand März 2013):
  • Ca. 10 Rappen pro Gigabyte Traffic
  • Ca. 1 Rappen pro 10'000 HTTP-Requests
Eine durchschnittliche Website wird ca. 10-20 Requests pro Seitenaufruf auslösen (pro Ressource ein Request, ausser, die Ressource ist lokal gecached im Browser, z.B. mittels mod_expires). Wenn ein Besucher im Durchschnitt 5 Seiten aufruft, so sind dies 100 Requests pro Besucher. Eine Page mit 2000 Besucher pro Tag wird damit auf 200'000 Requests im Tag kommen (=Hits), womit dies 20 Rappen pro Tag ausmacht. Je trafficreicher die Seite, desto höher werden die Kosten.

Eine News-Seite wie z.B. 20 Minuten Online mit täglich 468'000 Besucher (Mediadaten vom Februar 2013) à 20 Pageloads à 40 Assets verursacht andere Kosten: Dies sind täglich 374 Mio Hits, was pro Tag 370 Franken ausmachen würde. Dies wäre aber immer noch weitaus günstiger, als eine eigene High-Performance Infrastruktur zu betreiben.

Nicht beachtet sind hier die Traffic-Kosten per Gigabyte. Diese dürften durch die Caching-Mechanismen für eine normale Website aber nicht ins Gewicht fallen (meine Faustregel: pro 1000 monatliche Benutzer 1 GB pro Monat). Bei einem grossen News-Netzwerk mit viel Bild- und Videomaterial sieht das allerdings etwas anders aus. Allerdings kann man dann bei den CDN den Traffic vorab einkaufen, womit die Preise nochmals massiv tiefer sind.

Optimierung der Kosten

Die Anzahl HTTP-Requests kann man natürlich optimieren, indem man CSS und JavaScript Dateien je zusammenfasst, und mit CSS-Sprites arbeitet anstatt mit Einzelbildern. Dies hat dann ohnehin wiederum einen positiven Effekt auf die Seitenperformance.

Fazit

Interessant, wenn die Ladegeschwindigkeit ein wichtiges Geschäftskriterium ist. Tiefe Einstiegskosten erlauben es selbst kleinen Unternehmen, von CDN Gebrauch zu machen. Die Hauptvorteile kommen allerdings erst dann zum tragen, wenn entsprechende Übertragunsgvolumen technisch oder preislich durch klassisches Hosting zum Problem werden.

Sonntag, 3. März 2013

DOM Load mit sinnvoller Ladereihenfolge von JS und CSS beschleunigen

Für den Einsatz von Javascript-Widgets wie Slideshows, Lighboxes, und vielleicht noch den einen oder anderen Ajax-Request muss man beachten, dass man die Libraries und CSS-Files dazu in korrekter Reihenfolge lädt. Durch geschickte Deklarationsreihenfolge der Libraries lässt sich die Zeit verringern, bis die Website angezeigt wird.

Tipp: Deklarationsreihenfolge von CSS und JS beachten

Immer erst die CSS-, und erst danach die JS-Deklarationen - sofern dies die Applikationslogik zulässt. Wieso? Der Grund liegt in der Art der Parallelisierung der Downloads dieser Ressourcen.

Die meisten Browser blockieren den Download von im Dokument angegebenen Ressourcen nach einem Script-Tag, bis der Inhalt des Script-Tags gedownloadet, geparst und fertig ausgeführt ist. Dies ist soweit logisch, denn die Javascripts müssen sequentiell abgearbeitet werden, da sie unter Umständen das DOM verändern und von Aktionen vorangehender Scripts abhängig sein könnten. Anders sieht das bei CSS aus: Dies sind lediglich Styling-Informationen, und können allesamt parallel heruntergeladen werden (d.h. in der Regel 6 Files pro Domain aufs Mal, je nach Browser). Natürlich kann es sein, dass eine CSS-Rule eine andere wieder überschreibt, aber das führt nicht zu Inkonsistenzen im DOM.

Würde man nun also 2 externe Javascript-Dateien referenzieren, und danach 2 CSS-Dateien, so würden die CSS-Dateien erst heruntergeladen, nachdem die 2 Javascripts sequentiell durchgelaufen sind. Vorher blockiert der Browser jeden weiteren Ressourcen-Download. Dies sieht etwa so aus:


<script ... />
<script ... />
<link rel="stylesheet" ... />
<link rel="stylesheet" ... />

   50ms | 100ms | 150ms | 200ms |
--> JS1 --> JS2  
               --> CSS1
               --> CSS2


Die beiden JS werden geladen, und dann folgt der Rest parallel. Wie würde es aber aussehen, wenn wir zuerst die CSS, und dann die JS laden würden?


<link rel="stylesheet" ... />
<link rel="stylesheet" ... />
<script ... />
<script ... />  

   50ms | 100ms | 150ms | 200ms |
--> CSS1
--> CSS2
--> JS1 --> JS2

Angenommen, alle Files haben 50ms zum Laden, so hatten wir zuerst 150ms Ladezeit, nun sind es noch 100ms. Damit haben wir 30% Performance raus geholt.

Fazit

Weit hergeholt? Nein. Dieses Beispiel illustriert lediglich 2 Javascripts und 2 CSS-Dateien, alle von gleicher Grösse. In der realen Welt sieht es ganz anders aus. Fremdlibraries werden wie wild referenziert und  oft auch verkettet geladen, und eben in einer für den Browser ungünstigen Reihenfolge. Mit einer sinnvollen Parallelisierung holt man selbst bei guten Roundtrips schnell mal 50-100ms raus.

Natürlich könnte man nun sagen, man habe meinen Artikel über die Optimierung mittels Cache-Control-Header gelesen, und die JS-Dateien würden ja nur einmal heruntergeladen, und dann aus dem Browser-Cache bedient werden. Dies mag für subsequente Page-Aufrufe stimmen. Aber: Die JS-Dateien müssen dennoch jedes Mal geparst und ausgeführt werden, und das kostet Zeit. Auf einem Core-i7 mit Google Chrome sind dies bei der weit verbreiteten jQuery Library etwa 20ms, mit dem IE7 sind es immerhin ca. 100ms. Und dies bei jedem Seitenaufruf...

Fussnote

Natürlich gibt es diverse Ausnahmen, welche ich in diesem Artikel nicht erwähnt habe. Zum Beispiel lässt sich dem <script> Tag das "async" Attribut anhängen, womit die Scripts nicht aufeinander warten müssen. Des weiteren kennen moderne Browser intelligente Prediction-Modelle, über welche sie vorzubestimmen in der Lage sind, ob weitere Ressourcen schon mal gedownloadet, aber noch nicht ausgeführt werden sollen. Darauf bin ich natürlich nicht eingegangen, auch wenn moderne Browser diese Modelle in gewissen Situationen durchaus umsetzen. Hält man sich aber an obige Regel (Css-vor-Javascript), muss man sich darüber ja gar nicht erst den Kopf zerbrechen und ist immer auf der sicheren Seite.