Large amounts of main thread work can slow down your website. This article explains what main thread CPU activity is, how to measure it, and how to reduce main thread work.
What is main thread work?
Computers divide work into different processes and threads that mostly run independently from each other. This also lets them take advantage of multiple CPU cores and split work between them.
Minimizing main thread work is important as the page can't respond to user input if the event handler code is blocked by other work. These performance problems are reflected in metrics like Total Blocking Time and First Input Delay.
However, not all work is done on the main thread. For example, these tasks might be done in separate threads:
- Compositing (combining separate painted layers)
- Running code in web workers
Work that's done off the main thread usually has a lower performance impact.
Do you need to minimize main thread work?
Before beginning to optimize, keep in mind that main thread work does not directly impact user experience. For example, Lighthouse shows it as a Diagnostic metric, but it doesn't impact the overall Performance score. Instead of looking only at main thread work, check user-centric metrics like the Core Web Vitals to see how these CPU tasks affect your site performance.
Two seconds of work done before the initial render of the page will significantly slow down your website. But if a chat widget loads five seconds after all other content is visible, that will have a much smaller impact on your users.
How to minimize main thread work
What causes CPU activity on the main thread depends on your app, so the best way to minimize main thread work is to understand what your app is doing. Usually creating a performance recording in Chrome DevTools is the best way to do this.
However, here are two common reasons for unusually large amounts of main thread work.
Note that with server-side rendering the page is rendered before the client-side app initializes. This way the amount of main thread work is the same, but the user impact is much lower as the page content becomes immediately visible.
Many websites pull in resources from a variety of different providers, for example to show ads or a chat widget. Unlike with first-party code, you can't fix performance issues arising from these scripts yourself. Try contacting the customer support of the provider to see if they can help.
If that doesn't work, you have two options:
- Remove the third-party script, fixing the performance impact
- Creating a "facade", e.g. by showing a placeholder for a chat widget and only loading the full widget when the user tries to interact with it.
You should also ensure that third-party code isn't render-blocking, to reduce the performance impact on the user experience.
Main thread work in Chrome DevTools
Chrome DevTools lets you see exactly what happens on the main thread, so you can identify what CPU activity can be avoided.
Start by opening DevTools, selecting the Performance tab, and collecting a performance profile.
The performance recording can be really complex, but we'll quickly narrow it down so we only need to look at main thread tasks.
You can click on each lane in the performance recording to view more details. The blue bracket on the left indicates what lane is selected. After selecting the main thread lane DevTools shows an overall breakdown of main thread CPU activity on the page.
We can also select the Bottom-up view and group activity by domain in order to see whether our own code or third-party code is responsible for the CPU activity.
In this case the cookielaw.org domain also contributes to CPU activity, as well as several Chrome extensions that I've installed.
Click the arrow icon to expand each lane. For the main thread, this shows us a call stack with all the bits of code involved. Here we're looking at a public website with minified source code, so we get meaningless function names like
c.O. For your own website, you or a developer you're working with can run a test without minification, which will be easier to interpret.
Despite the minified code we can see that a lot of work is done in a function called
t.hydrate. This indicates that the page contains a client-side app that was pre-rendered on the server, and is then transformed from static HTML to an interactive app ("hydrated").
Zooming in shows that part of the hydration process involves repeated style recalculations (in purple). This is usually something to avoid, as work ends up being duplicated.
Let's look at the next big chunk of CPU work. After clicking on one of the CPU tasks, Chrome shows a breakdown of CPU activity for that task, as well as the URL that it's attributable to. In this case that's the OneTrust Banner SDK.
Read this article for an in-depth guide on how to profile your website using the Chrome DevTools Performance tab.
Main thread work in Lighthouse
Google's Lighthouse tool, which also powers the PageSpeed Insights lab data, can give you a breakdown of main thread work by activity type. Long chunks of CPU activity will increase the Total Blocking Time metric.
Main thread work in DebugBear
DebugBear can track CPU activity over time and alert you when there's a regression. Each test result also includes a full Lighthouse report.
DebugBear also monitors the high-level performance metrics for your website.
What are the different CPU activity categories used in Lighthouse?
Lighthouse uses the following categories:
- Script Evaluation
- Style & Layout
- Parse HTML & CSS
- Garbage Collection
- Script Parsing & Compilation
The Lighthouse source code shows exactly what's included in each category.
You may see a large amount of "Other" activity for a visually complex page. Many web performance testing environments don't have a GPU, so additional CPU work is required instead.