/ Web

Web-Performance messen

Die durchschnittliche Größe einer Website hat im Jahr 2016 die Marke von 2300 KB überschritten. Eine mittelgroße Website ist somit größer als das Installationsimage des 3D-Ego-Shooters “DOOM”, das 1993 erschien. Hatten Websites 2011 noch einen durchschnittlichen Umfang von knapp 750 KB, so verdoppelte sich die Größe auf 1500 KB im Jahr 2013 und wuchs bis 2016 weiter bis auf fast 2300 KB an.
pagesize
Quelle: mobifoge.com

Eine interessante Entwicklung ist jedoch festzustellen: Obwohl die Größe der meisten Websites unerbittlich wuchs, wurden die Top 10 Sites der Welt seit 2014 immer schlanker. Das Bewusstsein für schnelle und schlanke Websites hat sich bei den Big Playern bereits durchgesetzt. Nach 25 Jahren “Erwachsen werden” des World Wide Webs (Das WWW wird innerhalb des Europäischen Kernforschungslabors CERN eingesetzt), mit einer “Neues Framework? Muss ich einsetzen”-Phase tritt nun die Etappe des Bewusstseins für Performance und Usability ein.
alexa_top_10_weight_vs_all_sites
Quelle: mobiforge.com

Was ist Web-Performance?

Wikipedia beschreibt Web-Performance als Geschwindigkeit des Ladens und der Anzeige von Websites, die mit Treue und Zufriedenheit der Benutzer belohnt wird:

“Web performance refers to the speed in which web pages are downloaded and displayed on the user's web browser. Web performance optimization (WPO), or website optimization is the field of knowledge about increasing web performance. Faster website download speeds have been shown to increase visitor retention and loyalty and user satisfaction”

Eine schnellere Website hat auch kommerzielle Vorteile.
Kürzere Ladezeit resultiert in mehr Conversion in weniger Seitenabbrüche
und mehr Kundenzufriedenheit

Wie wird Web-Performance gemessen?

Was wird gemessen?

Bei der Messung soll die Wartezeit ermittelt werden, die der Nutzer nach seiner Anfrage an eine Seite auf die gewünschte Antwort wartet.

Die Verarbeitung einer HTML-Seite im Browser kann man in drei Teile gliedern: Verbindung mit Server, Verarbeitung auf dem Server und Verarbeitung im Client.

sec3iBl1YAC_LsROIjWPErQ

Aus technischer Sicht gibt es viele Faktoren, die gemessen und optimiert werden können. Beispielsweise:

  • Verarbeitungszeit des Servers
  • Anzahl Requests / HTTP2
  • Caching / Repeat View
  • Aufbau, Größe und Implementierung von HTML, CSS und JS
  • Bilder. Anzahl, Größe, Progressive?
    Aus Sicht des Benutzers ist jedoch nur die Zeit bedeutend, die er bis zur vollständigen Bearbeitung seiner Anfrage im Browser warten muss. Eine langsam übertragene, aber auf Performance im Client optimierte Seite kann unter Umständen schneller angezeigt werden, als eine schnell übertragene, mit schlechter Performance im Client. Aus der der Dauer eines einzelnen Verarbeitungsschritts kann man daher nicht direkt auf die vom Benutzer wahrgenommene Aufbau-Geschwindigkeit einer Seite schließen.
    Wie lange dauert es, bis ein Benutzer einen bedeutsamen Teil des Ergebnisses seiner Interaktion sieht?

Bekanntes Szenario: Benutzer sehen eine weiße Seite und / oder die Ladeanzeige. Dauert dieser Zustand zu lange, werden sie ungeduldig, kontrollieren die URL, laden die Seite neu. Im schlimmsten Fall geben sie auf und verlassen die Website (Es gibt bereits einige Studien zum Thema User Experience: SOASTA oder Nielsen Norman Group).

Was passiert an dieser Stelle? In diesem Teil der Verarbeitung baut der Browser eine Verbindung zum Server auf, siehe Schaubild 1 (1). Der Server bereitet die Antwort vor und sendet sie zurück (2).

Der weitere Teil der Verarbeitung geschieht im Client (3). Der lokale Aufbau der Seite kann trotz optimal erfolgter Verarbeitungen in (1) und (2) zu unnötigen Verzögerungen in der Darstellung führen. Die Priorisierung der anzuzeigenden Inhalte, um das Ergebnis einer Benutzerinteraktion und die wichtigsten weiteren Interaktionsmöglichkeiten schnellstmöglich anzuzeigen, nennt sich “Optimierung des kritischen Rendering Pfads”.
Wie lange dauert es, bis ein Benutzer mit der Seite (sprich: mit dem für ihn relevanten Teil der Seite) interagieren kann?

Ein weiteres ärgerliches Szenario: Die Seite ist zwar optisch vollständig geladen, lässt sich aber nicht bedienen. Die Ladeanzeige des Browsers zeigt zwar noch den Ladevorgang an, aber eine für den Anwender optisch vollständig geladene Website suggeriert die Möglichkeit einer Interaktion.
Mit welchen Methoden können Wartezeiten eines Benutzers ermittelt werden?

Die Verarbeitungsdauer im Client ist sowohl von der Ladezeit der Ressourcen als auch von der Effizienz der implementierten Anwendung abhängig. Deshalb reicht es nicht aus, die reine Übertragungsdauer des Contents zu messen. Sinnvoller ist es die Zeit zu ermitteln, die verstreicht, bis das Browserfenster mit sichtbarem Inhalt gefüllt ist. Die bekannteste und genaueste Methode diesen Wert zu ermitteln, ist der im Testtool webpagetest.org eingesetzte “Speed Index”.

Bei der oben genannten Methode wird eine optische Ermittlung des Lade-Fortschritts durchgeführt. Eine Alternative dazu stellt der “RUM SpeedIndex” dar (RUM - “Real User Monitoring”). Bei dieser Messmethode werden “Resource Timings” der Browser für die Berechnungen verwendet.

Sollte keine Möglichkeit bestehen, den Speed Index zu bestimmen, sind folgende Größen bedeutend: “Time To First Byte”, “Load Time” und Datenmenge.

Die zu übertragende Datenmenge einer Applikation ist ein besonderer Wert, der anders als “Ladezeitmessungen” unabhängig vom Datendurchsatz der Netzwerkverbindung ist und eine direkt optimierbare Größe darstellt.

Womit wird gemessen?

Die zuverlässigste Methode, die Performance einer Site zu bestimmen, ist eine genaue Untersuchung des Lade- und Verarbeitungsverhaltens mittels Browser-Entwicklertools. Es gibt unter anderem ein Performance-Modell namens “RAIL”, das man als Richtwert für die Ergebnisse eigener Anwendung verwenden kann.
rail
Quelle: developers.google.com

Die Kurzbeschreibung der Regeln:

  • Response: respond in under 100ms
  • Animation: render frames every 16ms
  • Idle: maximize idle time
  • Load: deliver content under 1000ms

Neben den Browser-Dev-Tools helfen diverse Online-Tools. Die bekanntesten sind webpagetest.org und Google Page Speed Insights.

Um eine Site regelmäßig und schnell zu kontrollieren, lohnt es sich den Vorgang zu automatisieren. Sitespeed.io bietet hierfür ein hilfreiches Werkzeug, das sich als NPM-Modul ins Projekt integrieren lässt und das Tests lokal durchführt. Zusätzlich wird ein Docker-Image angeboten, in dem alle Tests getrennt vom Host-System ablaufen können. Auch Webpagetest.org bietet ein NPM-Modul an, das aber die Tests an Remote-Server delegiert.

Webpagetest.org

Webpagetest.org bietet neben umfangreichen Tests von Timings und Datenmengen die Möglichkeit an, Videos der Tests aufzunehmen und einen Videovergleich zweier Messungen durchzuführen.

Die Hauptbestandteile des Ergebnisses sind: Eine farbige Zusammenstellung von Optimierungsgraden der wichtigsten Performance-Einflussfaktoren sowie eine Tabelle mit den wichtigsten Ladezeiten auf der gemessenen Seite.
screenshot-www-webpagetest-org-2016-06-27-09-34-12
Das Nonplusultra des Tools ist die Möglichkeit der genauen Messung des Speed Index. Anders als bei der Messung anhand der RUM-Timings erfolgt hier die Ermittlung nach Regeln des so genannten “Synthetischen Testens” , bei der jegliche Beeinflussungen des Clients und der Testumgebung durch die Messeinrichtung minimiert werden. Es werden keine Scripte in die zu messenden Sites injiziert. Für realitätsnahe Tests stehen weltweit Server zur Verfügung, für die Tests wird jedoch immer nur eine Browserinstanz pro Testserver gestartet. Die Ermittlung des Speed Index (und auch zum Beispiel des “First Paint”) erfolgt durch optische Erfassung des Ladefortschritts.

Messungen können anstatt mit Hilfe der sehr übersichtlichen Weboberfläche auch mittels einer REST-API durchgeführt werden. Im folgenden Beispiel wird ein Test gestartet, dessen Ergebnis auch in XML-Form zurückgegeben werden soll (“xmlUrl”).

http://www.webpagetest.org/runtest.php?url=www.sevenval.com&runs=2&f=xml&r=12345&k=[KEY]

<response>
 <statusCode>200</statusCode>
 <statusText>Ok</statusText>
 <requestId>12345</requestId>
 <data>
    <testId>
      160724_HV_RT2
    </testId>
    <ownerKey>
      key
    </ownerKey>
    <xmlUrl>
      http://www.webpagetest.org/xmlResult/160724_HV_RT2/
    </xmlUrl>
    <userUrl>
      http://www.webpagetest.org/result/160724_HV_RT2/
    </userUrl>
    <summaryCSV>
      http://www.webpagetest.org/result/160724_HV_RT2/page_data.csv
    </summaryCSV>
    <detailCSV>
      http://www.webpagetest.org/result/160724_HV_RT2/requests.csv
    </detailCSV>
    <jsonUrl>
      http://www.webpagetest.org/jsonResult.php?test=160724_HV_RT2
    </jsonUrl>
 </data>
</response>

Mit Hilfe eines von Marcel Duran (Web Performance Engineer bei Google) entwickelten NPM-Wrapper lassen sich Tests bequem als NPM-Task in das Projekt integrieren.
npm install -g sitespeed.io
Folgender Befehl startet einen Test und prüft alle 10 Sekunden, ob ein Testergebnis bereits vorhanden ist und zeigt ihn im Anschluss an.
webpagetest test https://www.sevenval.com -k [KEY] --poll 10
Ebenso ist es möglich Webpagetest in der CI-Umgebung zu verwenden. Folgender Befehl führt einen First-View-Test durch und vergleicht das Ergebnis mit den Vorgaben aus “testspecs.json”:
webpagetest test https://www.sevenval.com --first --poll --specs estspecs.json -k [APIKEY]
testspecs.json:

{
 "median": {
        "firstView": {
           "SpeedIndex":1000,
           "requests": 50,
           "render": 2000,
           "loadTime": 3000,
           "score_gzip": {
                "min": 90
           }
        }
   }
}

Das Ergebis ist dann ein Ergebniscode “2”, und die Ausgabe:

WebPageTest

    1) median.firstView.SpeedIndex: 2005 should be less than 1000
    ✓ median.firstView.requests: 46 should be less than 50
    ✓ median.firstView.render: 1894 should be less than 2000
    ✓ median.firstView.loadTime: 2062 should be less than 3000
    ✓ median.firstView.score_gzip: 100 should be greater than 90

4 passing (7ms)

1 failing

Der CI-Job kann angehalten und ein Deployment verhindert werden.

Ein Nachteil von Webpagetest ist es, dass die Tests nicht lokal durchgeführt werden können, d.h., dass während der lokalen Entwicklung keine Tests möglich sind. Für Tests wird ein Remote-Testserver benötigt, auf dem nur eine Messung gleichzeitig möglich ist. Das erschwert die Skalierung und kann längere Durchlaufzeiten von Messungen verursachen.

Vorteil: Wenn man keine eigenen WPT-Testserver aufsetzen möchte, kann man das kostenlose Angebot auf webpagetest.org verwenden (die API kann erst nach vorheriger Registrierung verwendet werden, es sind 200 Seitenaufrufe pro Tag erlaubt), man sollte dann aber je nach Server-Standort längere Wartezeiten in Kauf nehmen:
screenshot-www-webpagetest-org-2016-07-20-23-04-12

Sitespeed.io

Sitespeed.io bietet ähnlich viele Testmöglichkeiten wie Webpagetest.org. Der größte Unterschied ist aber, dass Messungen lokal und mittels RUM erfolgen.

Nebst npm-Modul bietet Sitespeed.io ein vorkonfiguriertes Docker-Image an, in dem Tests in Desktop-Browsern Chrome und Firefox durchgeführt werden können.

Das Tool testet, sofern es nicht anders konfiguriert wurde, auch alle Unterseiten der zu messenden Site und bildet dann das Ergebnis.

Das Ergebnis einer Messung ist ein Verzeichnis mit einigen HTML-Seiten (JSON- und XML-Darstellung der Messwerte sind ebenfalls vorhanden), auf denen alle Daten benutzerfreundlich abgebildet sind. Der Einfluss der einzelnen Größen auf die Performance wird durch farbige Auszeichnung dargestellt.
screenshot-examples-sitespeed-io-2016-06-22-09-14-42
Sitespeed.io kann auch als NPM-Task in das Projekt-Environment integriert werden. Es können "Performance-Budgets" definiert werden. Bei Nichteinhaltung der Grenzwerte wird eine Fehlermeldung beim Bauen eines Projekts auf ein Performance-Problem hinweisen. Eine TAP/JUnit XML-Ausgabe ist für die Integration in einer CI-Umgebung ebenfalls möglich.

Die Installation:
npm install -g sitespeed.io
Folgender Befehl führt einen Test einer Site samt Unterseiten aus zwei Ebenen im Chrome-Browser durch, es wird ein bestimmter Viewport und User-Agent festgelegt, die Verbindungsgeschwindigkeit wird gedrosselt:
sitespeed.io -u http://www.sevenval.com -d 2 --viewPort 400x300 --userAgent "My SUPER BROWSER" -b chrome --connection mobile3g
Ein gleicher Test mittels Docker sieht wie folgt aus:

docker run --privileged \
--name sitespeed \
--rm \
-v "$(pwd)":/sitespeed.io sitespeedio/sitespeed.io sitespeed.io \
-u https://www.sevenval.com \
-d 2 \
--viewPort 400x300 \
--userAgent "My SUPER BROWSER" \
-b chrome \
--connection mobile3g

In einem CI-Environment kann Sitespeed.io ebenfalls eingesetzt werden. Ein TAP-Test mit einem zu erfüllenden Budget “myBudget” könnte so initiiert werden:
sitespeed.io -u https://www.sevenval.com --wptHost www.webpagetest.org --wptKey MY_SECRET_API_KEY --tap --budget myBudget.json
Mit myBudget.json:

{
 "rules": {
   "default": 90
 },
 "timings": {
   "serverResponseTime": 300,
   "domContentLoadedTime": 700,
   "speedIndex": 1000
 },
 "wpt": {
   "SpeedIndex": 1000
 },
 "gpsi": {
   "score": 90
  }
}

Zu beachten ist, dass für den Test auch Webpagetest.org einbezogen werden kann, so dass zusätzlich der “echte” SpeedIndex ermittelt wird.

Zu den Nachteilen von Sitespeed.io gehört die weniger genaue RUM-Messmethode (ohne WPT-Zusatztests) sowie die fehlende Funktion der Aufnahme eines Videos. Ebenso können sich Fehler daraus ergeben, dass einige Messungen mittels Phantom.js erfolgen (Yslow) und nicht mit realen Browsern. Die meisten ermittelten Daten weichen dann von den im Browser-HTTP-Archivs (Ein HAR ist auch Bestandteil des Mess-Ergebnisses) stehenden ab.

Fazit

Das Bewusstsein für Web-Performance steigt. Es gibt eine Vielzahl von Tools, die es erlauben, eigene Sites bequem zu prüfen. Sitespeed.io und Webpagetest.org sind hilfreiche Werkzeuge, die sowohl über übersichtliche Weboberflächen bedient als auch als Prozesse einer Continuous-Integration-Umgebung eingesetzt werden können. Webpagetest liefert dabei sehr genaue Messergebnisse. Mit Sitespeed.io kann man dafür Tests ohne externe Server durchführen. Dadurch lässt sich Sitespeed.io auch besser skalieren.