v147 · developer trial · workers · perf

js-profiling in dedicated workers

The JS Self-Profiling API — sample-based, low-overhead CPU attribution — now works inside Dedicated Workers. Sites can finally measure where their worker time is going, gated by Document Policy as on the main thread.

concepts

  1. Worker Profile

    Spins up a Dedicated Worker that does some real CPU work, profiles it for ~2 seconds, then renders the captured frames as a hot-functions list.

  2. Trace upload

    Worker A runs the load and profiles it. Worker B aggregates the trace off the main thread into a compact payload, then navigator.sendBeacon fires it at a telemetry endpoint — the WICG-recommended pattern for RUM profiling at scale.

  3. Profile Comparator

    Runs an identical CPU-intensive task (prime factorisation) on both the main thread and a Dedicated Worker and profiles both with the JS Profiler API. Chrome 147 enables the Profiler inside workers — compare the sample traces and timings side by side.

  4. Profiler API Explorer

    Three-tab explorer. Main thread tab: configurable sample interval and buffer size, runs Fibonacci or sort workload, renders trace as a horizontal flame-graph. Worker tab: detects Profiler inside a Blob Worker and posts the trace back. Comparison tab: overlays main vs worker samples per function in a paired-bar chart.

  5. Compatibility Lab

    Detects the Profiler API on both main thread and inside a Worker. Runs a live profiler test in a blob worker and reports sample counts. Provides the performance.mark() fallback and the complete worker-messaging pattern for environments without Document-Policy: js-profiling.

why it shipped

Lots of work has moved off the main thread — image processing, parsing, AI inference, codecs. But the JS Self-Profiling API was main-thread-only, so the moment something interesting moved into a worker, sites lost the ability to attribute time. The fix is to apply the same Profiler primitive inside dedicated workers, gated by the same js-profiling Document Policy. Performance teams now get a complete picture of where execution time lands.

enabling it

The main-thread Profiler is stable — it is behind the Blink feature ProfilerAPI and works in Chrome 147+ (this page sends the required Document-Policy: js-profiling header). The dedicated-worker half is a separate, experimental Blink feature, ProfilerAPIForDedicatedWorker, and Chrome 152 stable does not enable it: the worker global has no Profiler until you launch Chrome with --enable-blink-features=ProfilerAPIForDedicatedWorker, or turn on chrome://flags/#enable-experimental-web-platform-features.

Both the main-thread and worker-global APIs were measured in this browser by driving the Worker Profile demo. Without the flag the demo reports the missing worker Profiler. With --enable-blink-features=ProfilerAPIForDedicatedWorker the worker global does expose Profiler — and construction then throws NotSupportedError: Failed to construct 'Profiler': Document Policy is not enabled for this context, even though the worker script response carries document-policy: js-profiling. Chrome 152 therefore cannot produce a worker profile either way; the demo reports that error instead of hanging, and the main-thread profile still works. A blob: dedicated worker behaves the same, which is why the feature check profiler-supported-in-dedicated-worker stays red.

references

implementation reference

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