Start · Sprachen · JavaScript · Referenz · WorkerGlobalScope.performance

WorkerGlobalScope.performance

Eigenschaft

Gibt das <code>Performance</code>-Objekt des Workers zurück, mit dem sich Laufzeiten im Worker-Kontext hochauflösend messen und protokollieren lassen.

seit JavaScript Baseline: alle modernen Browser (Worker-Unterstütz Kategorie: webapi

Signatur

WorkerGlobalScope.performance

Beschreibung

Die schreibgeschützte Eigenschaft performance der Schnittstelle WorkerGlobalScope liefert ein Performance-Objekt für den jeweiligen Worker (Dedicated Worker, Shared Worker oder Service Worker). Im Worker ist sie global als self.performance bzw. einfach performance erreichbar, genau wie window.performance im Hauptthread.

Typische Einsatzgebiete sind die Messung rechenintensiver Aufgaben, die man bewusst in einen Worker auslagert: Bildverarbeitung, Parsing großer Datenmengen, Kryptografie oder WebAssembly-Berechnungen. Mit performance.now() erhält man hochauflösende Zeitstempel, mit performance.mark() und performance.measure() benannte Messpunkte und Zeitspannen aus der User Timing API.

Wichtig: Jeder Worker hat seinen eigenen Zeitursprung (performance.timeOrigin). Dieser liegt beim Start des Workers, nicht beim Laden der Seite. Werte von performance.now() aus Worker und Hauptthread lassen sich deshalb nicht direkt vergleichen. Man muss sie erst über timeOrigin auf eine gemeinsame Zeitbasis umrechnen.

Einige Teile der Performance-API gibt es im Worker nicht, zum Beispiel performance.timing und performance.navigation (beide veraltet) sowie Navigations-Einträge. Verfügbar sind unter anderem now(), timeOrigin, mark(), measure(), getEntries*(), clearMarks()/clearMeasures() und Resource-Timing-Einträge für fetch()-Anfragen, die der Worker selbst stellt.

Rückgabewert

Typ
Performance
Beschreibung
Das Performance-Objekt des aktuellen Worker-Kontexts. Die Eigenschaft ist schreibgeschützt.

Beispiele

Rechenaufgabe im Worker messen

// worker.js
self.addEventListener('message', (event) => {
  const start = performance.now();

  // Rechenintensive Aufgabe: Primzahlen zählen
  let count = 0;
  for (let n = 2; n < event.data; n++) {
    let isPrime = true;
    for (let d = 2; d * d <= n; d++) {
      if (n % d === 0) { isPrime = false; break; }
    }
    if (isPrime) count++;
  }

  const duration = performance.now() - start;
  self.postMessage({ count, duration });
});

// main.js
const worker = new Worker('worker.js');
worker.addEventListener('message', ({ data }) => {
  console.log(`${data.count} Primzahlen in ${data.duration.toFixed(1)} ms`);
});
worker.postMessage(1_000_000);
78498 Primzahlen in 142.3 ms

Messpunkte mit mark() und measure()

// worker.js
self.onmessage = async ({ data: url }) => {
  performance.mark('fetch-start');
  const response = await fetch(url);
  const json = await response.json();
  performance.mark('fetch-end');

  performance.mark('process-start');
  const summary = json.length;
  performance.mark('process-end');

  performance.measure('Laden', 'fetch-start', 'fetch-end');
  performance.measure('Verarbeiten', 'process-start', 'process-end');

  const measures = performance.getEntriesByType('measure')
    .map(({ name, duration }) => ({ name, duration: Math.round(duration) }));

  self.postMessage({ summary, measures });
  performance.clearMarks();
  performance.clearMeasures();
};
{ summary: 500, measures: [ { name: 'Laden', duration: 87 }, { name: 'Verarbeiten', duration: 3 } ] }

Zeitstempel zwischen Worker und Hauptthread abgleichen

// worker.js
self.postMessage({
  // Absolute Zeit (ms seit Unix-Epoche) statt relativem Wert
  absolute: performance.timeOrigin + performance.now()
});

// main.js
const worker = new Worker('worker.js');
worker.onmessage = ({ data }) => {
  const mainAbsolute = performance.timeOrigin + performance.now();
  console.log(`Nachrichtenlaufzeit: ${(mainAbsolute - data.absolute).toFixed(2)} ms`);
};
Nachrichtenlaufzeit: 0.84 ms

// Wichtig · Fallstricke

  • Eigener Zeitursprung: performance.now() im Worker beginnt beim Start des Workers bei 0. Um Werte mit dem Hauptthread zu vergleichen, immer performance.timeOrigin + performance.now() verwenden.
  • Getrennte Eintragslisten: Marks und Measures aus dem Worker erscheinen nicht in window.performance.getEntries() und umgekehrt. Ergebnisse muss man per postMessage() übertragen.
  • Reduzierte Genauigkeit: Zum Schutz vor Timing-Angriffen wie Spectre runden Browser die Zeitstempel (oft auf 100 µs oder gröber). Nur mit Cross-Origin-Isolation (COOP/COEP-Header) gibt es genauere Werte. Firefox mit privacy.resistFingerprinting rundet noch stärker.
  • Nicht verfügbar im Worker: performance.timing, performance.navigation und Navigation-Timing-Einträge. Ebenso performance.memory, das es nur in Chromium gibt und das nicht standardisiert ist.
  • Speicher: Viele mark()-Aufrufe in langlebigen Workern (z. B. Service Workern) sammeln Einträge an. Deshalb regelmäßig clearMarks() und clearMeasures() aufrufen.
  • Kompatibilität: Wird in allen aktuellen Browsern unterstützt (Chrome, Edge, Firefox, Safari). Sehr alte Safari-Versionen hatten im Worker kein performance. Im Zweifel mit 'performance' in self prüfen.