Main Thread

A web browser uses threads to handle the scheduling and execution of code. Modern web browsers use multiple threads to handle webpage-related tasks.

Pagespeed optimization ultimately starts with one thread: the Main thread. The Main thread is where the browser does most of the work needed to display a page. When debugging optimization issues, you'll likely start by examining the main thread.

Since the main thread can only handle one task at a time, pagespeed optimization needs to focus on reducing performance bottlenecks caused by tasks over utilizing the main thread.

Viewing the main thread

One of the best ways to diagnose page performance issues is to examine the performance tab using Google Chrome's development tools to view the tasks running on the main thread. These tasks are displayed on a timeline. Although it might not be obvious, only one type of task can occur at a time.

Examining Tasks

Items in the first row of the main thread timeline will always be named "Task."

There are usually short gaps between tasks indicated by whitespace.

In some cases, these gaps are longer due to the browser waiting on another thread to finish a task like downloading a resource.

Blocking Tasks

When the main thread is dedicated to a specific task for more than 50ms, the timeline flags this task as a potential performance issue. During the debugging process, it's useful to find any blocking tasks and investigate further.

  • Long tasks are designated with red, indicating that this task is blocking the main thread for more than 50ms.
  • Normal tasks that block the main thread for less than 50ms are indicated with a grey bar.

The rows below each task are the various actions within the task. Actions might be nested. For example, a JavaScript function might trigger another function. In this case, the parent function appears in the row below the "task" heading. Then, the child functions appear in the following rows below it.

Additionally, you can also click on a task to examine this "calltree", which is a breakdown of the activities occurring in the task. By examining this specific calltree and timeline, we can see that the order of activities in this task are:

  1. Evaluate Script: actions related to the browser reading and executing code from a separate JavaScript file.
  2. Parsing HTML: actions related to the browser reading the page's HTML file.

Expand the activities within the calltree for the breakdown of each activity: Based on the time for each action in this calltree, it's clear that the performance issue for this task is caused by a JavaScript function that takes 2999.4ms to execute.

Order and Types of Tasks

There are several types of tasks that occur on the main thread.

Tasks can appear on the first row of the timeline under the generic "Task" annotation or nested under other tasks. Understanding what row you'd expect to see a particular task on will help with debugging more quickly.

Parsing tasks

The browser reads and interprets a string, such as the contents of an HTML or CSS file.

  • Parse HTML
  • Parse Stylesheet

These tasks usually appear in the first row when .html or .css files are parsed.

However, a parsing task can also be triggered by JavaScript.

<script>
  function createHTML() {
    document.body.innerHTML += `<p>Added via JS</p>`;
  }
  createHTML();
</script>

For example, innerHTML triggers a Parse HTML task, which will appear under the associated function instead of on the first row.

Script Evaluation and Events

JavaScript contents are parsed and executed. These tasks appear in the first row when directly read from an external .js file.

  • Evaluate Script
  • Event (e.g. Event: visibilitychange)

Script Evaluation appears as a nested task when it's an inline script.

// index.html
<html>
  <head>
    <script>
      (function()
        function firstFunction() {
          ...
        }
        firstFunction()
      }())
    </script>
...

Inline script evaluation will appear nested under the Parse HTML task.

Recalculate Style, Layout, Update Layer Tree

These types of tasks are related to calculating how the content will be eventually rendered (visually displayed) to the user.

Recalculate Style is a top-level task when CSS is referenced in an external stylesheet file.

Conversely, inline styles triggered nested tasks.

// index.html
<html>
  <head>
    ...
    <style>
      ...
    </style>
...

The Recalculate Style task will be nested under the Parse HTML task when the styles are inline.

Paint, Composite Layers

Graphical tasks related to visually 'painting' content to the user based on the calculated styles, layout, and layer tree.

Conclusions

The main thread handles one task at a time. For pagespeed optimization, the ultimate goal is to reduce the work required by the main thread to render a page. Ideally, this will result in the page becoming interactive and useful to the user more quickly.