Start · Sprachen · JavaScript · Referenz · Window.performance

Window.performance

Eigenschaft

Liefert das <code>Performance</code>-Objekt des Fensters, mit dem sich hochauflösende Zeitmessungen, Navigations- und Ressourcen-Timings erfassen lassen.

seit JavaScript Baseline: alle Browser (seit ca. 2012; auch in Web Kategorie: webapi

Signatur

window.performance

Beschreibung

Die schreibgeschützte Eigenschaft window.performance gibt das Performance-Objekt des aktuellen Browsing-Kontexts zurück. Es ist der Einstiegspunkt für die High Resolution Time API, die User Timing API (mark(), measure()) sowie die Performance Timeline mit Navigations-, Ressourcen- und Paint-Einträgen.

Du verwendest performance, wenn du genaue Laufzeiten von Code messen willst. Anders als Date.now() liefert performance.now() einen monotonen Zeitstempel in Millisekunden mit Nachkommastellen, gemessen ab performance.timeOrigin (in der Regel der Beginn der Navigation). Dieser Wert ist unabhängig von Änderungen an der Systemuhr und eignet sich deshalb für Benchmarks, Animationen und Monitoring.

Wichtige Mitglieder des zurückgegebenen Objekts:

  • now() – aktueller hochauflösender Zeitstempel relativ zu timeOrigin
  • timeOrigin – absoluter Startzeitpunkt (Unix-Epoche in ms)
  • mark(name) / measure(name, start, end) – eigene Messpunkte und Zeitspannen
  • getEntries(), getEntriesByType(type), getEntriesByName(name) – Einträge der Performance Timeline abfragen
  • clearMarks(), clearMeasures(), clearResourceTimings() – Puffer leeren
  • toJSON() – serialisierbare Darstellung

Für die laufende Beobachtung neuer Einträge (etwa Largest Contentful Paint oder Long Tasks) ist PerformanceObserver besser geeignet als wiederholtes Abfragen mit getEntries().

Rückgabewert

Typ
Performance
Beschreibung
Das Performance-Objekt des aktuellen Fensters. Die Eigenschaft ist schreibgeschützt; innerhalb eines Fensters wird immer dasselbe Objekt zurückgegeben.

Beispiele

Laufzeit einer Funktion messen

const sortiereGrosseListe = () => {
  const daten = Array.from({ length: 200_000 }, () => Math.random());
  return daten.sort((a, b) => a - b);
};

const start = performance.now();
sortiereGrosseListe();
const dauer = performance.now() - start;

console.log(`Sortieren dauerte ${dauer.toFixed(2)} ms`);
Sortieren dauerte 48.30 ms

User Timing: Marken und Messungen für einen API-Aufruf

const ladeBenutzer = async () => {
  performance.mark('fetch-start');
  const response = await fetch('https://jsonplaceholder.typicode.com/users');
  const benutzer = await response.json();
  performance.mark('fetch-ende');

  const messung = performance.measure('benutzer-laden', 'fetch-start', 'fetch-ende');
  console.log(`${benutzer.length} Benutzer in ${Math.round(messung.duration)} ms geladen`);

  // Aufräumen, damit der Puffer nicht wächst
  performance.clearMarks();
  performance.clearMeasures();
};

ladeBenutzer();
10 Benutzer in 182 ms geladen

Navigations- und Ressourcen-Timings auswerten

window.addEventListener('load', () => {
  const [nav] = performance.getEntriesByType('navigation');
  console.log('TTFB:', Math.round(nav.responseStart - nav.requestStart), 'ms');
  console.log('DOMContentLoaded:', Math.round(nav.domContentLoadedEventEnd), 'ms');

  const langsam = performance
    .getEntriesByType('resource')
    .filter((r) => r.duration > 200)
    .map((r) => `${r.name} (${Math.round(r.duration)} ms)`);

  console.log('Langsame Ressourcen:', langsam);
});
TTFB: 94 ms DOMContentLoaded: 612 ms Langsame Ressourcen: ["https://example.com/app.js (340 ms)"]

Neue Einträge mit PerformanceObserver beobachten

const observer = new PerformanceObserver((liste) => {
  for (const eintrag of liste.getEntries()) {
    console.log('LCP:', Math.round(eintrag.startTime), 'ms', eintrag.element);
  }
});

observer.observe({ type: 'largest-contentful-paint', buffered: true });

// Absolute Zeit eines relativen Zeitstempels berechnen
const absolut = new Date(performance.timeOrigin + performance.now());
console.log(absolut.toISOString());
2024-05-01T10:15:30.123Z LCP: 1240 ms <img class="hero">

// Wichtig · Fallstricke

  • Reduzierte Genauigkeit: Zum Schutz vor Timing-Angriffen (Spectre) runden Browser performance.now() ab, typischerweise auf 5 µs bis 100 µs, in Firefox mit privacy.resistFingerprinting sogar auf 100 ms. Eine feinere Auflösung gibt es nur in cross-origin-isolierten Seiten (Header Cross-Origin-Opener-Policy und Cross-Origin-Embedder-Policy).
  • Relativ statt absolut: performance.now() zählt ab timeOrigin, nicht ab der Unix-Epoche. Zeitstempel aus verschiedenen Fenstern oder Workern kannst du nur über timeOrigin vergleichen.
  • Veraltete APIs: performance.timing und performance.navigation sind veraltet. Verwende stattdessen performance.getEntriesByType('navigation') (PerformanceNavigationTiming).
  • Pufferlimits: Der Puffer für Ressourcen-Timings ist standardmäßig auf etwa 250 Einträge begrenzt. Mit performance.setResourceTimingBufferSize() kannst du ihn vergrößern oder mit clearResourceTimings() leeren. Ruf nach vielen mark()-Aufrufen clearMarks() auf, damit kein Speicherleck entsteht.
  • Cross-Origin-Ressourcen: Bei fremden Ressourcen sind detaillierte Timings (z. B. DNS- oder Verbindungsdauer) nur dann verfügbar, wenn der Server den Header Timing-Allow-Origin sendet. Andernfalls stehen dort 0-Werte.
  • Kompatibilität: now(), mark() und measure() werden von allen modernen Browsern unterstützt. Optionen wie measure(name, { start, end, detail }) gibt es erst seit etwa 2020/2021. In Web Workern erreichst du das Objekt über self.performance, in Node.js über das globale performance oder require('node:perf_hooks').
  • Rechne bei Benchmarks mit Schwankungen durch JIT-Aufwärmphase, Garbage Collection und gedrosselte Hintergrund-Tabs. Miss deshalb mehrfach und bilde den Median.