demo · v147

Trace upload

Worker A runs a real CPU-heavy load. A second worker profiles it with the JS Self-Profiling API at a chosen sample rate, aggregates the trace into a hot-functions list off the main thread, and emits a compact payload ready for navigator.sendBeacon.

Behind a flag: JS Self-Profiling in dedicated workers ships behind the Document Policy js-profiling, gated by chrome://flags/#enable-experimental-web-platform-features in Chrome 147. This page is served with the required policy header and reports unavailable browsers instead of fabricating traces.
samples collected
—
distinct functions
—
trace size (raw)
—
payload size (aggregated)
—
functionsamples
no profile yet

Aggregated payload (what we'd send to a telemetry endpoint)

no payload yet
pipeline idle

What's happening

  1. Worker A spins up a Worker that runs naïve fib(28), a heap-allocating JSON.parse, and an array sort.
  2. Worker A wraps the load in new self.Profiler({ sampleInterval }), calls .stop(), posts the raw trace.
  3. Main thread hands the raw trace to Worker B, which aggregates by leaf function — the "process traces in a worker" pattern from the WICG explainer.
  4. The compact payload is shown above. The button calls navigator.sendBeacon('/telemetry/profile', payload) for real.
// inside worker A (Chrome 147, Document-Policy: js-profiling)
const profiler = new self.Profiler({ sampleInterval: 10, maxBufferSize: 10000 });
doExpensiveWork();
const trace = await profiler.stop();
self.postMessage({ kind: 'trace', trace });

// main thread → worker B
workerB.postMessage({ kind: 'aggregate', trace });

see also

implementation reference

Need the exact API surface, compatibility boundaries, errors, lifecycle, and source links? Read the matching gendn reference ↗