Signatur
Beschreibung
Das Profiler-Interface gehört zur JS Self-Profiling API. Damit kann eine Webanwendung ihre eigene JavaScript-Ausführung als Stichproben-Profil aufzeichnen. Die Engine hält in regelmäßigen Abständen (sampleInterval) den aktuellen Aufrufstapel fest. Wenn Sie stop() aufrufen, erhalten Sie ein Promise, das mit einem ProfilerTrace-Objekt erfüllt wird. Dieses Objekt enthält die Felder resources, frames, stacks und samples.
Der Hauptnutzen liegt im Real User Monitoring: Die DevTools messen nur auf dem Rechner der Entwickler. Mit Profiler sehen Sie dagegen, welche Funktionen bei echten Nutzern auf echten Geräten Rechenzeit verbrauchen, etwa beim Seitenstart, bei langen Aufgaben (Long Tasks) oder bei langsamen Interaktionen (INP). Die Traces schicken Sie typischerweise an einen Server, fassen sie dort zusammen und werten sie aus.
Das Profiling startet sofort, sobald Sie den Konstruktor new Profiler(options) aufrufen. Eine eigene start()-Methode gibt es nicht. Wichtige Mitglieder:
Profiler.sampleInterval(nur lesen): das tatsächlich verwendete Abtastintervall in Millisekunden. Es kann größer sein als der angeforderte Wert.Profiler.stopped(nur lesen): gibt an, ob der Profiler bereits beendet ist.Profiler.stop(): beendet die Aufzeichnung und gibtPromise<ProfilerTrace>zurück.- Event
samplebufferfull: wird ausgelöst, wennmaxBufferSizeerreicht ist. Danach werden keine weiteren Stichproben aufgezeichnet.
Die API funktioniert nur, wenn das Dokument mit dem HTTP-Header Document-Policy: js-profiling ausgeliefert wird. Fehlt der Header, wirft der Konstruktor einen Fehler.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $options Pflicht | Object | Einstellungen für den Profiler (Konstruktor-Argument von new Profiler(options)). |
|
| $options.sampleInterval Pflicht | number | Gewünschter Abstand zwischen zwei Stichproben in Millisekunden. Der Browser kann den Wert aufrunden. In Chrome liegt er meist bei mindestens 10 ms, unter Windows bei etwa 16 ms. Den tatsächlichen Wert lesen Sie über profiler.sampleInterval. |
|
| $options.maxBufferSize Pflicht | number | Maximale Anzahl an Stichproben, die im Puffer gespeichert werden. Ist die Grenze erreicht, wird samplebufferfull ausgelöst und die Aufzeichnung endet. |
Beispiele
Einen Codeabschnitt profilen
// Server muss senden: Document-Policy: js-profiling
const heavyWork = () => {
let sum = 0;
for (let i = 0; i < 5e7; i++) sum += Math.sqrt(i);
return sum;
};
const profileTask = async () => {
if (!('Profiler' in window)) {
console.warn('JS Self-Profiling API nicht verfügbar');
return;
}
const profiler = new Profiler({ sampleInterval: 10, maxBufferSize: 10_000 });
console.log('Tatsächliches Intervall:', profiler.sampleInterval, 'ms');
heavyWork();
const trace = await profiler.stop();
console.log('Stichproben:', trace.samples.length);
console.log('Frames:', trace.frames.length);
};
profileTask();
Trace auswerten: häufigste Funktionen ermitteln
const topFunctions = (trace, limit = 5) => {
const counts = new Map();
for (const { stackId } of trace.samples) {
if (stackId === undefined) continue; // Leerlauf, kein JS aktiv
const { frameId } = trace.stacks[stackId]; // oberster Frame
const frame = trace.frames[frameId];
const name = frame.name || '(anonym)';
const file = trace.resources[frame.resourceId] ?? '?';
const key = `${name} @ ${file}:${frame.line ?? '?'}`;
counts.set(key, (counts.get(key) ?? 0) + 1);
}
return [...counts].sort((a, b) => b[1] - a[1]).slice(0, limit);
};
const profiler = new Profiler({ sampleInterval: 10, maxBufferSize: 5000 });
// ... Anwendungscode läuft ...
setTimeout(async () => {
const trace = await profiler.stop();
console.table(topFunctions(trace));
}, 2000);
Seitenstart profilen, samplebufferfull behandeln und Trace senden
const profiler = new Profiler({ sampleInterval: 10, maxBufferSize: 1000 });
const finish = async () => {
if (profiler.stopped) return;
const trace = await profiler.stop();
navigator.sendBeacon('/api/profiles', JSON.stringify({
url: location.href,
interval: profiler.sampleInterval,
trace
}));
};
// Puffer voll: Aufzeichnung endet, Daten trotzdem senden
profiler.addEventListener('samplebufferfull', () => {
console.warn('Profiler-Puffer voll');
finish();
});
window.addEventListener('load', () => setTimeout(finish, 0));
// Wichtig · Fallstricke
- Document-Policy ist Pflicht: Das Dokument muss mit
Document-Policy: js-profilingausgeliefert werden. Ohne diesen Header wirftnew Profiler()einenNotAllowedError. In iframes muss die Richtlinie zusätzlich erlaubt werden. - Browser-Unterstützung: Die API ist experimentell und nur in Chromium-Browsern (ab Chrome 94) verfügbar, nicht in Firefox und Safari. Prüfen Sie vorher mit
'Profiler' in window. Sie ist auch in dedizierten Workern nutzbar. - Cross-Origin-Skripte: Frames aus Skripten fremder Herkunft erscheinen nur mit vollständigen Namen und Positionen, wenn das Skript CORS-fähig geladen wird (
crossorigin-Attribut undAccess-Control-Allow-Origin). Sonst fehlen diese Details oder die Frames werden ausgelassen. - Intervall wird aufgerundet: Verlassen Sie sich nicht auf den angeforderten
sampleInterval, sondern lesen Sie den tatsächlichen Wert ausprofiler.sampleInterval. - Kein Neustart: Ein beendeter Profiler lässt sich nicht erneut starten. Legen Sie dafür eine neue Instanz an. Mehrere Profiler gleichzeitig sind möglich, verursachen aber zusätzlichen Aufwand.
- Performance: Das Profiling kostet etwas Rechenzeit, und Traces können groß werden. Profilen Sie in der Praxis nur einen kleinen Teil der Nutzer und begrenzen Sie
maxBufferSize. Stichproben ohnestackIdstehen für Leerlauf, also Zeit ohne aktives JavaScript. - Datenschutz: Traces enthalten Skript-URLs und Funktionsnamen. Achten Sie beim Versand an Ihren Server darauf, dass keine sensiblen Daten in URLs stehen, etwa Tokens in Query-Strings.