Skip to main content

See How CPU Processing Impacts Page Speed

Browsers run rendering and nearly all JavaScript on a single main thread, and that thread does one thing at a time. While a long task is running the page can't paint an update or respond to user interactions, so CPU work impacts page speed and responsiveness.

Every DebugBear lab test records what tasks ran while the page was loading.

This article covers the CPU timeline in a test result, the script-level breakdown behind Total Blocking Time, and the task detail that shows what code caused a delay.

DebugBear CPU timeline​

Each result contains a timeline of work done on the page main thread. It's drawn below the filmstrip, so you can see what the browser was busy with while a visitor was still looking at an unfinished page.

Most of this work is usually JavaScript execution. The timeline also covers style and layout calculation, painting, HTML parsing and garbage collection.

Each bar is one task, and the width of the bar shows how long the task ran.

The color tells you what kind of work took up most of that time: yellow for scripting, purple for style and layout, green for painting, blue for HTML parsing, and gray for garbage collection or anything else.

CPU timeline below the rendering filmstrip

Hovering over a task shows how long it ran and how much of that counted toward Total Blocking Time. (Only the time past the first 50 ms of each task counts.)

The tooltip also breaks the task down by type of work and names the script DebugBear attributed it to. That's often enough to recognize the code without opening anything else.

View script-specific processing time​

Expanding the Total Blocking Time metric shows a larger version of the same timeline, plus a table of blocking time by script file.

A single long task tells you when the page froze. The table tells you which file is behind the problem across the whole page load.

Blocking time attributed to each script file

Some of the time can't be assigned to a file, and DebugBear groups that as Unattributable. That's usually browser work like layout, or code written inline in the HTML document.

You can also view a list of third-party scripts to see how other service providers used on your website impact performance.

tip

If you see metric variance caused by third-party scripts, you can block ads and analytics tools in your device settings.

Third party CPU breakdown

Additional CPU time metrics​

The Metrics tab shows a more granular breakdown of CPU processing time. For example, you can view how much time was spent on:

  • JavaScript execution
  • Style calculations
  • Layout and rendering
  • HTML Parsing
  • Garbage collection
  • Painting

CPU time breakdown

DebugBear tracks each of these over time like any other metric, so you can watch one kind of work on its own.

If your page gets slower you can then check whether CPU processing time went up, and which kind of work it was.

Inspect CPU tasks​

Click on any task in the timeline to see what that task was doing. The view that opens covers one task only, so everything in it adds up to the duration shown at the top.

Use the arrows next to the heading to step through neighboring tasks without going back to the timeline.

CPU task detail with the activity breakdown

The task detail view shows:

  • How long the task ran, and where it sat in the page load
  • The activity breakdown, splitting the task into Scripting, Style & Layout, Parsing and other work
  • The call tree, listing the calls the task made with the total time each one took and how much of that was spent in the call itself rather than in what it called
  • File attribution, naming the scripts the work belonged to, with the CPU time each file was responsible for

The task view separates Total and Self time.

A call with a large total but a small self time spent its time in the calls below it, so keep opening those. If the two numbers are close the call is doing the work itself, and that's the code to change.

Call tree view​

The call tree shows the specific activities that a long task consists of. For example, Chrome might run JavaScript code, then parse the HTML code for a new element, and clean up memory usage with garbage collection.

For Total Blocking Time the tree only covers tasks that were long enough to block interactions. For CPU time it covers the whole page load.

Opening a row shows the calls made from it, so you can follow a stack down from the script that started the work to whatever it ended up triggering.

In the example below a script file runs for just over a second. Inside that call the JavaScript engine stops to handle interrupts, the browser recalculates styles and lays out the page, and a garbage collection runs. Further down, promise callbacks parse more HTML and run an event listener.

Call stack in the call tree for blocking tasks

info

Switch the filter from All to 5+ ms to only see calls that spent 5 ms or more in themselves. Long tasks are usually made up of a few expensive calls and a long tail of cheap ones, so this leaves you with the ones worth reading.

What the call tree entries mean​

Functions from your own code appear with their names. But much of a page load is browser and JavaScript engine work, which shows up under names from Chrome's tracing. Entries starting with v8. or V8. come from V8, Chrome's JavaScript engine.

These are the entries you're most likely to run into:

EntryWhat it means
v8.run, EvaluateScriptA script file running from top to bottom, usually just after it was downloaded
v8.compileCompiling JavaScript before it can run, which is where large bundles lose time before doing anything useful
FunctionCallA function the browser called into, such as an event handler or a callback. The function name is shown in brackets when it is known
RunMicrotasksPromise callbacks, run at the end of the task that resolved them
TimerFire, FireAnimationFrameCallbacks scheduled with setTimeout or requestAnimationFrame
EventDispatch, XHRReadyStateChangeListeners responding to a page event, or to an XHR (XMLHttpRequest) response arriving
ParseHTMLParsing HTML into the DOM, the element tree the browser renders from, including HTML a script wrote
UpdateLayoutTree, LayoutWorking out which styles apply, then where every element goes
Paint, PrePaint, CommitTurning the laid out page into pixels on screen
MinorGC, MajorGC, BlinkGCGarbage collection, reclaiming memory the page no longer uses
V8.StackGuard, V8.BytecodeBudgetInterruptBookkeeping inside running JavaScript, such as the engine deciding to optimize a function that has run many times
(anonymous)A function with no name in the source, for example a callback defined inline

Garbage collection and compilation are worth calling out, as neither is code you wrote and both grow with the amount of JavaScript on the page.

Shipping less JavaScript, or deferring what's not needed for the first screen, brings both of them down.

Detailed CPU task data​

Everything above comes with every page test result. DebugBear builds it from the trace each test already records, so collecting it costs nothing.

But trace data only names the calls a task went into. It can't see inside a single long function: if one of your functions runs for 300 ms without calling anything the browser reports, the call tree says so and stops there.

Collecting detailed CPU task data fills that gap. DebugBear then runs Chrome's JavaScript profiler during the test, which samples the JavaScript stack as the page loads and records which functions were running. That turns one long call into the functions it spent its time in.

The call tree then goes as deep as your code does, and each row still names the file it came from.

In the task below, 766 ms of parsing and script evaluation unfolds into a chain of minified application functions, ending in a querySelectorAll call that takes 28 ms on its own. Without the profile the task would stop at the script that was running.

A deep call stack recorded with detailed CPU task collection

Lab tests only collect this data if you ask for it. You can enable it for a whole project or for a single page.

warning

Collecting more detailed CPU profiling data requires extra resources, and it can increase your page spede metrics.

Enable it for a whole project​

Open the project's lab test settings and switch on Collect Detailed CPU Task Data. Every page in the project then collects it, unless a page overrides the setting.

The Collect Detailed CPU Task Data toggle in the project's lab test settings

Enable it for a single page​

Open the page's settings, choose Add Advanced Setting, and pick Detailed CPU Task Data. The page then has its own dropdown with three options:

  • Use Project Default, which follows the project
  • Collect Detailed CPU Task Data
  • Don't Collect Detailed CPU Task Data, which keeps one page out of it while the rest of the project collects it

The Detailed CPU Task Data option in a page's advanced settings

Use Remove to drop the setting from the page again and go back to the project default.