[Proposal] An API to allow webpage JavaScript to profile its own performance


#1

Web developers want to understand how their webapps perform on real user devices, and they want to know which parts of their code are slow so they can target optimizations.

Currently, developers have to either profile their site in their own browser (not representative) or pepper their code with boilerplate timing statements (incomplete, doesn’t scale well). Facebook went one step further and implemented a sampling profiler with JavaScript and SharedArrayBuffers (which suffered from accuracy and performance drawbacks).

The existing approaches for debugging webapp slowdowns in the field are laborious, don’t have complete coverage, and have serious overheads. A native API for pages to profile their own JS execution would make debugging web performance a lot easier. Note that this API would only allow profiling the page’s JS execution, not any browser internals like DOM implementation. And since similar functionality can be polyfilled with JS, there should be no security or privacy concerns.

The collected profiles can be sent to analytics servers for aggregation and automatic analysis.

Rough ideas for an API:

window.performance.startProfiling(options) => Promise (resolves to a Profiler object)

Profiler.stopProfiling() => Promise

Profiler.cancelProfiling() => Promise

I wrote up a more detailed proposal and motivation here: https://github.com/vdjeric/js-self-profiling


#2

I really like that proposal. I suspect that profiling would have some overhead, but:

  • It’s opt-in only
  • It’s probably less overhead than implementing profile as part of your JS like Facebook is doing now

A few things that seem missing in your proposal:

  • How does one collect the profiling info? I’m assuming some form of PerformanceEntry/PerfObserver, but that’s not explicitly mentioned.
  • Have you thought about sampling? The JS profiling command could just be imperitively sampled, but it may make sense to also add sampling to the HTTP header based profiling instructions.

#3

This sounds awesome! Some questions:

  • Should there be header similar to Timing-Allow-Origin that lets a third party permit profiling of its scripts (even if they’re not same-origin)?
  • Should the JavaScript-Start-Profiling header be on individual <script/> HTTP responses instead of at the page level?

And finally: would you rather I post questions like this to the GitHub repo instead :-)?


#4

How does one collect the profiling info? I’m assuming some form of PerformanceEntry/PerfObserver, but that’s not explicitly mentioned.

The Profiler.stopProfiling() call would return a Promise which resolves to a ProfilingResult JSON object containing the profile samples. ProfilingResult would be a JS object containing the information described at the bottom of the github doc.

Have you thought about sampling? The JS profiling command could just be imperitively sampled, but it may make sense to also add sampling to the HTTP header based profiling instructions.

Oh absolutely, this should be a sampling profiler that drives its own sampling. The idea is that performance.startProfiling(options) would turn on the sampling profiler and it would not stop collecting samples until Profiler.stopProfiling() was called (which would return all the samples at once).

The JavaScript-Start-Profiling: <float> HTTP response header line described in the doc instructs the browser to start sampling at the specified interval even before page is fully transmitted. It wouldn’t stop profiling until Profiler.stopProfiling() was called (or maybe we could have some other mechanism like an event for returning the pageload profile).


#5

Should there be header similar to Timing-Allow-Origin that lets a third party permit profiling of its scripts (even if they’re not same-origin)?

That sounds like a good idea, but I will let others chime in before adding it to the proposal, since I haven’t thought enough about the privacy implications.

What use case are you envisioning for this? Third party IFrame ads or something else?

Should the JavaScript-Start-Profiling header be on individual HTTP responses instead of at the page level?

I was thinking it should be at the document level (page or iframe) and ignored otherwise. Is there a use-case for profiling on a script-by-script basis?

And finally: would you rather I post questions like this to the GitHub repo instead :-)?

I guess we should move further discussion to GitHub to keep the topics threaded. I will file Github issues for the topics you raised.


#6

Regarding a profiling HTTP header, a page can just insert at the start of the document head. This proposal right now is only targeting JavaScript execution so there’s nothing that can happen before this point that this API would collect data for AFAIK. If an future extension to the specification was to include browser events then catching event before dom loading would be useful and an HTTP header would be a great way to cover it.

I believe for now it’s not needed.

I think exploring what we want to do for 3rd party script is interesting, particularly for 3rd party performance libraries and middle ware. Let’s continue to explore this in the issues that vdjeric has filed.


#7

It looks like discussion has moved to GitHub issues for now: https://github.com/vdjeric/js-self-profiling/issues