Kategorien
Design HTML/CSS JavaScript & jQuery Programmierung Webdesign

HTML5-APIs im Einsatz: So misst du Geschwindigkeiten mit User Timing und Navigation Timing

Gerade komplexe Webanwendungen setzen der Rechenleistung des Clients häufig zu. Vor allem auf mobilen Geräten ist es wichtig, besondere Vorsorge dafür zu treffen, dass alles flott läuft. Mit der neuen User-Timing-API können Ladezeiten einfach und vor allem präzise per JavaScript getestet werden. Denn die Messwerte beziehen ihre Werte der High-Resolution-Time-API, welche Zeiten auf die Mikrosekunde genau messen kann. Mit der Navigation-Timing-API ist es zudem möglich, Ladezeiten einer Website anhand vordefinierter Messpunkte zu ermitteln. Dank der komplexen und teils präzisen Messmöglichkeiten können Entwickler gut feststellen, an welchen Stellen innerhalb einer Anwendung es hakt.

Präzise messen per User-Timing-API

Mit der User-Timing-API ist es möglich, innerhalb einer Webanwendung die Geschwindigkeit zwischen mehreren vorher definierten Punkten zu messen. Dazu müssen jeweils ein Start- sowie ein Endpunkt für die Messung festgelegt werden. Diese können an beliebiger Stelle innerhalb eines Skriptes liegen. Das JavaScript-Objekt „performance“ besitzt mehrere Methoden, mit denen die notwendigen Messpunkte definiert werden können.

var messung_start = performance.now();

Die Methode now() beginnt eine Messung an beliebiger Stelle innerhalb einer Webanwendung. Sie kann beispielsweise innerhalb eines Skriptes platziert werden, das eine rechenintensive Funktion ausführt. Im Gegensatz zum Date()-Objekt, welches die aktuelle Systemzeit als Zeitstempel wiedergibt, gibt die User-Timing-API die Zeit in Millisekunden mit mehreren Nachkommastellen aus. Willst du beispielsweise herausfinden, wie viel Zeit vom ersten Messpunkt bis zum Laden eines Bildes vergeht, platzierst du den zweiten Messpunkt innerhalb eines load-Events.

document.getElementsByTagName("img")[0].addEventListener("load", function() {
  var messung_ende = performance.now();
}, false);

Die Differenz der beiden Werte messung_start und messung_ende ergibt dann die Zeit, die vergangen ist.

Verschiedene Messpunkte mit mark() definieren

Statt einzelne Messpunkte per now() zu setzen und diese einer Variablen zuzuordnen, gibt es die Möglichkeit, Messpunkte mit der Methode mark() zu setzen. Jedem dieser Messpunkte wird eine eindeutige Bezeichnung zugewiesen.

performance.mark("start");
…
performance.mark("ende");

Über die Methode measure() lässt sich anschließend die Differenz zweier Messpunkte berechnen. Die Methode erwartet drei Werte. Mit dem ersten Wert wird eine Bezeichnung für die Differenz festgelegt. Es folgen die Bezeichnungen für die beiden Messpunkte, für welche die Differenz berechnet werden soll.

performance.measure("differenz", "start", "ende");

Im Beispiel wird die Differenz zwischen den Messpunkten start und ende berechnet. Um die einzelnen Messwerte auszulesen, gibt es die Methode getEntriesByType(). Damit ist es möglich, für die per mark() und measure() gesetzten Punkte sowohl die Bezeichnungen als auch die berechneten Zeiten zu ermitteln.

var messpunkte = performance.getEntriesByType("mark");
var messdifferenzen = performance.getEntriesByType("measure");

Im Beispiel werden die per getEntriesByType() ausgegebenen Bezeichnungen und Werte als Array jeweils einer Variable übergeben. Anschließend können wir alle Informationen zu den Messungen ausgeben.

console.log(messpunkte[0].name + ": " + messpunkte[0].startTime);
console.log(messpunkte[1].name + ": " + messpunkte[1].startTime);
console.log(messdifferenzen[0].name + ": " + messdifferenzen[0].duration);

Die Eigenschaft name gibt die jeweilige Bezeichnung des Messpunktes beziehungsweise der berechneten Differenz aus. Bei per mark() gesetzten Messpunkten wird die gemessene Zeit per startTime; bei per measure() berechneten Differenzen wird diese per duration ausgegeben. Im Beispiel wird alles in die Browserkonsole geschrieben.

Statt Messpunkte und -berechnungen anhand ihres Types anzusprechen, erlaubt getEntriesByName() auch das Ansprechen anhand ihres Namens.

var messpunkte = performance.getEntriesByName("start");
console.log(messpunkte[0].name + ": " + messpunkte[0].startTime);

Im Beispiel wird der Messpunkt start, der über die Methode mark() gesetzt wurde, einer Variablen übergeben und anschließend in die Konsole geschrieben.

Messpunkte und -berechnungen entfernen

Will man einzelne oder alle Messpunkte oder -berechnungen löschen, ist dies mit den Methoden clearMarks() und clearMeasures() möglich. Den Methoden kann die Bezeichnung des zu löschenden Wertes übergeben werden.

performance.clearMarks("start");

Im Beispiel wird der Messpunkt start gelöscht. Werden die beiden Methoden ausgeführt, ohne dass eine Bezeichnung übergeben wird, so löscht du auf diese Weise alle vorher festgelegten Messpunkte.

performance.clearMarks();

Ladezeiten einer Website mit der Navigation-Timing-API ermitteln

Anders als die User-Timing-API muss die Navigation-Timing-API auf die präzise Zeitmessung im Mikrosekundenbereich verzichten. Stattdessen werden die Zeiten per einfachem Zeitstempel gemessen. Dafür ist es jedoch sehr einfach, die Ladezeiten einer Website anhand vorgegebener Messpunkte zu ermitteln. So können Sie etwa die Zeit messen, die vom „Entladen“ eines zuvor geöffneten Dokumentes bis zum fertig geladenen Dokument vergeht. Eingeleitet werden alle Messpunkte mit performance.timing. Es folgt eine Eigenschaft, welche den Messzeitpunkt vorgibt.

console.log(performance.timing.navigationStart);

Im Beispiel wird per navigationStart die Zeit ermittelt, zu der im zuvor geöffnete Dokument das unload-Event ausgeführt wird. Die Navigation-Timing-API gibt die Zeit als gängigen Zeitstempel in Millisekunden wieder. Im Beispiel wird der Zeitstempel in die Konsole geschrieben.

console.log(performance.timing.domLoading);
console.log(performance.timing.domComplete);

Im zweiten Beispiel wird zunächst der Zeitpunkt gemessen, an dem der Browser beginnt, den DOM-Baum zu laden. Als ermitteln wir den Zeitpunkt, zu dem der DOM-Baum fertig geladen ist.

Willst du statt Zeitstempel die jeweilige Dauer der einzelnen Ladezeiten wissen, musst du  zuerst den aktuellen Zeitstempel ermitteln. Anschließend können alle per performance.timing ermittelten Werte von diesem Zeitstempel subtrahiert werden.

window.addEventListener("load", function() {
  var jetzt = new Date().getTime();
  console.log(jetzt - performance.timing.domComplete);
}, false);

Im Beispiel wird nur die Zeitdifferenz bis zum komplett geladenen DOM-Baum in die Konsole geschrieben. Insgesamt stehen 21 verschiedene Eigenschaften zur Verfügung, welche die Zeit zu einem bestimmten Punkt innerhalb des Ladeprozesses messen.

Neben timing gibt es noch das navigation-Objekt, welches zwei Eigenschaften besitzt. Die Eigenschaft type gibt Aufschluss darüber, wie ein Dokument aufgerufen wurde.

console.log(performance.navigation.type);

Die Eigenschaft gibt eine Zahl zurück, die dann Null ist, wenn das Dokument per Link oder Direkteingabe aufgerufen wurde. Wurde die Seite neu geladen, wird 1 zurückgegeben. Wurde das Dokument per Vor- oder Zurückfunktion des Browsers aufgerufen, wechselt der Wert auf 2. Der Wert 255 wird immer dann ausgegeben, wenn keine der anderen genannten Möglichkeiten in Frage kommt.

Wurde die Seite per Redirect aufgerufen, gibt redirectCount die Anzahl der Weiterleitungen aus, die ausgeführt wurden, bis das aktuelle Dokument geladen wurde.

console.log(performance.navigation.redirectCount);

Browsersupport

Die User-Timing-API funktioniert in allen gängigen Browsern, einschließlich Internet Explorer 10+. Für ältere Browser gibt es ein Polyfill, welches aber die Unterstützung der High-Resolution-Time-API voraussetzt. Diese wird von Chrome ab Version 20 und Firefox ab Version 15 unterstützt. Der Internet Explorer unterstützt diese ebenfalls ab Version 10.

Die Navigation-Timing-API wird bereits von älteren Versionen der genannten Browser unterstützt. Das heißt, im Chrome und Firefox können sie unbedenklich eingesetzt werden. Der Internet Explorer unterstützt sie seit Version 9.

Links zum Beitrag

Beitragsbild: Michal Jarmoluk auf Pixabay

(Der Beitrag erschien erstmals im Dezember 2014 und wird seitdem aktuell gehalten. Das letzte Update erfolgte im April 2019.)

Von Denis Potschien

Denis Potschien ist seit 2005 freiberuflich als Kommunikationsdesigner tätig, seit Anfang 2010 im Kreativkonsulat in Iserlohn, einem Büro für Gestaltung und Kommunikation. Dort betreut er kleine und mittelständische Unternehmen ebenso wie kommunale Körperschaften und Organisationen aus Südwestfalen und dem Ruhrgebiet.

Als Webdesigner und -entwickler gehören HTML5 und CSS3 zu seinen Kernthemen, weshalb er dazu 2013 ein Buch geschrieben hat. „Pure HTML5 und CSS3“ richtet sich an alle, die Vorkenntnisse haben, sich aber bisher mit HTML5 und CSS3 nicht oder nur am Rande beschäftigt haben.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.