-
Notifications
You must be signed in to change notification settings - Fork 17
Description
(Admittedly, this is implementation-specific, but.. this implementation quirk is the reason for this spec'd header..)
I heard some concerns about the overhead of when document-policy: js-profiling is set. (Before Profiler.start() has been called). I confirmed ~3% overhead during the Speedometer benchmark.
Background
The CL that adds the header in Chromium says:
[when the] document policy is alive, pre-warm the V8 profiler. This significantly reduces profiler startup time by ensuring that compiled code is built with the appropriate metadata.
This pre-warming flips on V8 EagerLogging mode which tracks execution contexts, scripts, initializes V8 profiler instances, and quite a few things. (Later, once theProfiler.start() is called, these V8 profiler instances call CPUProfiler::startProfiling, and properly collect samples.
I do know that a fresh non-warmed CpuProfiler::StartProfiling cost can be kinda big. (DevTools now shows this as 'Profiling Overhead', but 'V8 Sampling Profiler Startup' would be a more accurate name.) The cost is ~50ms on a loaded theverge.com page. Meanwhile if it's started at the beginning of pageload, it's <1ms.
I'm assuming that pre-warming with EagerLogging was selected to avoid the risk of this long task occurring at a sensitive time.
Overhead Measurement
After some quick benchmarking environment setup, I grabbed some numbers..
I ran Speedometer 2.1 a couple times, in 3 different setups. One runs' results look like this:
Baseline (no policy):
Arithmetic Mean: 127.8 ‡ 1.1 (0.83%)
Arithmetic Mean: 128 ‡ 1.7 (1.3%)
Policy enabled (yeah, just the response header):
Arithmetic Mean: 124 ‡ 1.5 (1.2%)
Arithmetic Mean: 125 ‡ 1.5 (1.2%)
Policy enabled + Profiler started:
Arithmetic Mean: 114 ‡ 1.2 (1.1%)
Arithmetic Mean: 117 ‡ 2.3 (2.0%)
This looks like 3% overhead with EagerLogging. And 10% overhead with profiler started.
(Of course I'd love to see if someone's run similar tests with more rigor)
Developer usecases
I see four styles of use of the Profiler:
- A sampled audience capture from load. 1% of sessions get extra telemetry collected, and this header is set for them. Profiler is invoked at the start of page load.
- If profiler is started early, there's not much point of this EagerLogging pre-warm.
- A sampled audience capture of specific interactions. (Presumably the facebook.com usecase?). 1% of sessions get the header. Profiler isn't invoked at pageload, but will be invoked later to capture other SPA navigations, interactions of interest...
- Here, the EagerLogging mode trades off some overhead for a smaller task at
start(). Makes sense.
- Here, the EagerLogging mode trades off some overhead for a smaller task at
- A 'report slow stuff' button. This whole investigation was motivated by a partner who wants to offer a feature where users can report sluggishness and hit a button to 'record' the problematic scenario. So, we'd want the Profiler available 100% of the time, even if it is only invoked <1%.
- The EagerLogging overhead is prohibitive to this approach. A long task at profiler startup is fine, though.
- Sampled audience capture of specific interactions (but very basic). Developers/teams with less sophisticated setup may not have the infra to coordinate conditional response headers. So they'd prefer to just keep the header on for everyone and make the Profiling choice completely clientside.
- The overhead here will also be disruptive, depending on how important the overhead/observability tradeoff is to them..
- random/idle tracing, with the goal of obtaining an aggregate view of overall page execution. (As suggested by @acomminos below)
EagerLogging pre-warm is moot for 1, a win for 2, and a loss for 3, 4.
Do folks have thoughts on how we can help the 3 & 4 developers?
@yoavweiss floated a possibility.. we have two modes: the eager prewarm mode and a lazy on-demand one. Seems attractive. Though I also wonder if there's another resolution to case 2 above..
