Skip to content

How the duration is measured

Stefan Krause edited this page Sep 27, 2023 · 7 revisions

Goal

This benchmark tries to measure the duration of some table operations in the browser. That means we want to compute the duration starting from the click event until all repainting has finished. An alternative approach would be to measure just the javascript duration. We're not going this approach since we're interested in the complete client side duration (wall clock) and that includes the duration for rendering. Let's take a look at the performance tab: Screenshot 2023-09-21 at 9 03 24 PM The selection shows what we want: The duration is the timespan from the start of the click to the end of the paint event. Painting events are colored green. So we're looking for the end of the green bar. Chrome automation tools like puppeteer, playwright and webdriver can log the same events that the performance tab uses for its display.

Some more details

The click event is pretty easy to identify and the invariant is that there must be exactly one such event. We're interested in the start timestamp of that event. Some frameworks will perform the javascript logic during the click event which is the simplest case shown above. Other frameworks can delay javascript logic and execute them in a request animation frame callback or a timer event like shown here: Screenshot 2023-09-21 at 9 18 10 PM Can you spot the problem? There are two green bars. A small one after the click and the other after the timer. We're interested in the second green bar.

Specification

Due to some changes prior to chrome 117 there's now a commit event that marks the end of rendering: Screenshot 2023-09-26 at 8 10 58 PM

Duration is measured as the difference between the start of the click event and the first commit event that follows the last fireAnimationFrame, timerFire, layout or functioncall event. If no commit event is found this way take the last commit event. Only events of the main browser process are processed.

Unit tests

There are a few unit tests for that logic implemented in computeDuration.test.ts. We'll go through them here. The selection displays the duration we're measuring.

Ignore events from other processes

cample causes a commit event on other processes. We're only processing events of the main browser process, i.e. the events outside the selection are ignored. Screenshot 2023-09-26 at 8 24 15 PM

Use the commit event after the layout event

Better react has two commit events. A very small one near the blue line and a second after function call and layout. The second commit is used, since it's the commit after the layout. Screenshot 2023-09-26 at 8 28 11 PM

Use the commit event after the functioncall event

Select causes no layout event for most frameworks. For arrowjs we want the commit after the function call (below the timer): Screenshot 2023-09-26 at 8 48 56 PM

Use the commit event after the fireAnimationFrame event

dojo issues two commit events. The first after a layout event, but then a fireAnimationFrame event causes a second commit, which we take as the end point: Screenshot 2023-09-26 at 9 09 57 PM If we zoom in we see both commits: Screenshot 2023-09-26 at 9 11 50 PM

Ignore timer with no following commit

blazor-wasm has a timer callback that doesn't cause any rendering. We're using the commit event before that timer. Screenshot 2023-09-26 at 9 19 34 PM

Ignore second commit after hit test

Some frameworks have hit tests and a commit following the hit test. We're ignoring this combination since we're using the first commit after a fireAnimationFrame, timerFire, layout or functioncall. Screenshot 2023-09-26 at 9 22 54 PM

Links