Signatur
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
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);
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();
};
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`);
};
// Wichtig · Fallstricke
- Eigener Zeitursprung:
performance.now()im Worker beginnt beim Start des Workers bei 0. Um Werte mit dem Hauptthread zu vergleichen, immerperformance.timeOrigin + performance.now()verwenden. - Getrennte Eintragslisten: Marks und Measures aus dem Worker erscheinen nicht in
window.performance.getEntries()und umgekehrt. Ergebnisse muss man perpostMessage()ü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 mitprivacy.resistFingerprintingrundet noch stärker. - Nicht verfügbar im Worker:
performance.timing,performance.navigationund Navigation-Timing-Einträge. Ebensoperformance.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äßigclearMarks()undclearMeasures()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 selfprüfen.