Performance profiling with the Timeline
The Timeline panel lets you record and analyze all the activity in your application as it runs. It's the best place to start investigating perceived performance issues in your application.
Timeline panel overview
The Timeline has three primary sections: an overview section at the top, a records view, and a toolbar.
- To start or stop a recording, press the Record toggle button (see Making a recording).
- Press the Clear recording button to clear records from the Timeline.
- The Glue async events mode lets you more easily correlate asynchronous events to their causes (see About nested events).
- You can filter the records shown in the Timeline according to their type or duration (see Filtering and searching records).
During a recording, a record for each event that occurs is added to the Records view in a "waterfall" presentation. Records are categorized into one of four basic groups: Loading, Scripting, Rendering, and Painting. These records are color-coded as follows:
For example, the recording below is of an HTML page being loaded into Chrome. The first record (Send Request) is Chrome's HTTP request for the page, followed by a Receive Response record (for the corresponding HTTP response), some Receive Data records (for the actual page data), and then a Finish Loading record. For a complete list of events recorded by Timeline and their descriptions, see the Timeline event reference.
When you hover over a Timeline record, a pop-up appears with detailsabout the associated event. For example, the screenshot below showsdetails for a Finish Loading record associated with an image resource. The Timeline event reference explains the details available for each record type.
In addition to the detailed Records view, you can inspect recordings in one of three modes:
- Events mode shows all recorded events by event category.
- Frames mode shows your page's rendering performance.
- Memory mode shows your page's memory usage over time.
The Events mode provides an overview of all events that were captured during the recording, organized by their type. At a glance, you can see where your application is spending the most time, and on what types of tasks. The length of each horizontal bar in this view corresponds to time that event took to complete.
When you select a range of time from the Events view (see Zooming in on a Timeline section), the Records view is restricted to only show those records.
Horizontal lines across the Frames view represent frame rate targets for 60 FPS and 30 FPS. The height of a frame corresponds to the time it took to render that frame. The colors filling each frame indicate the percentage of time taken on each type of kind of task.
The time to render a frame is displayed atop of the Records view. If you hover over the displayed time, additional information appears about the frame, including the time spent on each type of task, CPU time, and the calculated FPS.
See Timeline demo: Diagnosing and fixing forced synchronous layout for a demonstration of using Frames mode.
About clear or light-gray frames
You may notice regions of a frame that are light-gray or clear (hollow). These regions indicate, respectively:
- Activity that was not instrumented by DevTools
- Idle time between display refresh cycles.
The frames in the recording below show both un-instrumented activity and idle time.
Want more details on the empty white space within the bars? Read Chrome Engineer Nat Duca's explanation, which describes how you can evaluate if you were bottlnecked by the GPU.
About the green bars
Painting is a two-step process that includes: draw calls and rasterization.
- Draw calls. This is a list of things you'd like to draw, and its derived from the CSS applied to your elements. Ultimately there is a list of draw calls not dissimilar to the Canvas element's: moveTo, lineTo, and fillRect. Although, they have different names in Skia, Chrome's painting backend, it's a similar concept.
- Rasterization. The process of stepping through those draw calls and filling out actual pixels into buffers that can be uploaded to the GPU for compositing.
So, with that background what is the difference between the solid green bars and empty green bars?
The empty green bars are the rasterization. A worker thread spawned by the compositor is what handles these.
Both are paint, they just represent different sub-tasks of the job. If you're having performance issues you can look at what properties you're changing. Then, see if there is a compositor-only way to achieve the same ends. CSS Triggers can help with identifying a solution to this.
Viewing frame rate statistics
The average frame rate and its standard deviation represented are displayed along the bottom of the Timeline panel for the selected frame range. If you hover over the average frame rate, a pop-up appears with additional information about the frame selection:
- Selected range -- The selected time range, and the number of frames in the selection.
- Minimum Time -- The lowest time of the selected frames, and the corresponding frame rate in parentheses.
- Average Time -- The average time of the selected frames, and the corresponding frame rate in parentheses.
- Maximum Time -- The maximum time for the selected range, and the corresponding frame rate in parentheses.
- Standard Deviation -- The amount of variability of the calculated Average Time.
- Time by category -- The amount of time spent on each type of process, color-coded by type.
The Memory view shows you a graph of memory used by your applicationover time and maintains a counter of the number of documents, DOMnodes, and event listeners that are held in memory (that is, thathaven’t been garbage collected).
Memory mode can't show you exactly what is causing a memory leak, but it can help you identify what events in your application may be leading to a memory leak. You can then use the Heap Profiler to identify the specific code that is causing the leak.
Making a recording
To make a recording, you start a recording session, interact with your application, and then stop recording. It helps to know in advance the kind of activity you want to record — for example, page loading, scrolling performance of a list of images, and so forth, and then stick to that script.
To make a recording:
- Open the page you want to record.
- Open the Timeline panel and start recording by doing one of the following:
- Click the round record button at the bottom of the Timeline panel.
- Press the keyboard shortcut Ctrl+E, or Cmd+E on Mac.
The Record button turns red during a recording.
Recording a page load
A common task is to record a page loading from the initial network request. Keyboard shortcuts are useful in this scenario, as they let you quickly start a recording, re-load the page, and stop the recording.
To record a page load:
- Open any web page in a new tab or window.
- Open the Timeline and press Cmd+E (Mac) or Ctrl+E (Windows/Linux) to start recording.
- Quickly press Cmd+R or Ctrl+R to reload the browser page.
- Stop the recording when the page has finished loading (look for the red event marker).
Your recording should look something like the following. The firstrecord (Send Request) is Chrome's HTTP request for the page, followed by a Receive Response record for the corresponding HTTP response, followed by one or more Receive Data records, a Finish Loading record, and a Parse HTML record.
See the Timeline event reference for details on each record type.
Tips for making recordings
Here are some tips for making recordings:
- Keep recordings as short as possible. Shorter recordings generally make analysis easier.
- Avoid unnecessary actions. Try to avoid actions (mouse clicks, network loads, and so forth) that are extraneous to the activity you want to record and analyze. For instance, if you want to record events that occur after you click a “Login” button, don’t also scroll the page, load an image and so forth.
- Disable the browser cache. When recording network operations, it’s a good idea to disable the browser’s cache in the DevTools Settings panel.
- Disable extensions. Chrome extensions can add unrelated noise to Timeline recordings of your application. You can do one of the following:
Analyzing Timeline recordings
This section provides tips for analyzing Timeline recordings.
Viewing details about a record
When you select a record in the Timeline, the Details pane displays additional information about the event.
Certain details are present in events of all types, such as Duration and CPU Time, while some only apply to certain event types. For information on what details each kind of record contains, see the Timeline event reference.
When you select a Paint record, DevTools highlights the region of the screen that was updated with a blue semi-transparent rectangle, as shown below.
DOMContentLoaded and Load event markers
The Timeline annotates each recording with a blue and a red line that indicate, respectively, when the DOMContentLoaded and load events were dispatched by the browser. The DOMContentLoaded event is fired when all of the page’s DOM content has been loaded and parsed. The load event is fired once all of the document’s resources (images and CSS files, and so forth) have been fully loaded.
Locating forced synchronous layouts
Layout is the process by which Chrome calculates the positions and sizes of all the elements on the page. Normally, Chrome performs layouts "lazily" in response to CSS or DOM updates from your application. This allows Chrome to batch style and layout changes rather than reacting to each on demand. However, an application can force Chrome to perform a layout immediately and synchronously by querying the value of certain layout-dependent element properties such as
element.offsetWidth. These so called "forced synchronous layouts" can be a big performance bottleneck if repeated frequently or performed for large DOM tree.
The Timeline identifies when your application causes a forced asynchronous layout and marks such records with yellow warning icon (). When you select the record, the details pane contains a stack trace of the offending code.
If a record contains a child record that forced a layout, the parent record is marked with a slightly dimmed yellow icon. Expand the parent record to locate the child record that caused the forced layout.
See the Forced Synchronous Layout demo for a demonstrationof detecting and fixing these kinds of performance issues.
About nested events
Events in Timeline recordings sometimes are nested visually beneath another event. You expand the "parent" event to view its nested "child" events. There are two reasons why the Timeline nests events:
- Synchronous events that occurred during the processing of an event that occurred previously. Each event internally generates two atomic events, one for the start and one for the end, that are converted to a single "continuous" event. Any other events that occur between these two atomic events become children of the outer event.
The following screenshot shows an example of nested synchronous events. In this case, Chrome was parsing some HTML (the Parse HTML event) when it found several external resources that needed to be loaded. Those requests were made before Chrome has finished the parsing, so the Send Request events are displayed as children of the Parse HTML event.
Coloring of Timeline records with nested events
Timeline bars are color coded as follows:
- The first, darkest part of the bar represents how long the parent event and all of its synchronous children took.
- The next, slightly paler color represents the CPU time that the event and all its asynchronous children took.
- The palest bars represent the time from the start of first asynchronous event to the end of last of its asynchronous children.
Selecting a parent record will display the following in the Details pane:
- Event type summary in text and visualized in a pie chart.
- Used JS Heap size at this point in the recording, and what this operation's effect was to the heap size.
- Other details relevant to the event.
Filtering and searching records
You can filter the records shown according to their type (only show loading events, for example), or only show records longer or equal to 1 millisecond or 15 milliseconds. You can also filter the view to show events that match a string.
While looking at all the events, you may want to hunt for one, but maintain context of what's around it. In this case, you can find without filtering. Press Ctrl+F (Window/Linux) or Cmd+F (Mac), while the Timeline has focus to show those that contain the search term.
Zooming in on a Timeline section
To make analyzing records easier, you can “zoom in” on a section of the timeline overview, which reduces accordingly the time scale in the Records view.
To zoom in on a Timeline section, do one of the following:
- In the overview region, drag out a Timeline selection with your mouse.
- Adjust the gray sliders in the ruler area.
Here are some more tips for working with Timeline selections:
- "Scrub" the recording with the current selection by dragging the area between the two slider bars.
- Swiping left or right with two fingers moves the current Timeline selection.
- Swiping up or down with two fingers expands or contracts the current Timeline selection, respectively.
Scrolling the mouse wheel up or down while hovering over a Timeline selection expands and contracts the selection, respectively.
Saving and loading recordings
You can save a Timeline recording as a JSON file, and later open it in the Timeline.
To save a Timeline recording:
- Right+click or Ctrl+click (Mac only) inside the Timeline and select Save Timeline Data…, or press the Ctrl+S keyboard shorcut.
- Pick a location to save the file and click Save.
To open an existing Timeline recording file, do one of the following:
- Right-click or Ctrl+click inside the Timeline and select Load Timeline Data..., or press the Ctrl+O keyboard shortcut.
- Locate the JSON file and click Open.
User-produced Timeline events
Applications can add their own events to Timeline recordings. You can use theconsole.timeStamp() method to add an atomic event to a recording, or theconsole.time() andconsole.timeEnd() methodsto mark a range of time that code was executing. For example, in the following recording the
console.timeStamp() was used to display an "Adding result" event. See Marking the Timeline in Using the Console for more information.
View CPU time in recordings
You will see light gray bars appearing above the Timeline records, indicating when the CPU was busy. Hovering over a CPU bar highlights the Timeline region during which the CPU was active (as shown below). The length of a CPU bar is typically the sum of all the (highlighted) events below it in the Timeline. If these don't match, it may be due to one of the following:
- Other pages running on the same threads as the page being inspected (for example, two tabs open from the same site, with one site doing something in a
- Un-instrumented activity.
Timeline event reference
This section lists and describes the individual types of records that are generated during a recording, organized by type, and their properties.
Common event properties
Certain details are present in events of all types, while some only apply to certain event types. This section lists properties common to different event types. Properties specific to certain event types are listed in the references for those event types that follow.
- Aggregated time
- For events with nested events, the time taken by each category of events.
- Call Stack
- For events with child events, the time taken by each category of events.
- CPU time
- How much CPU time the recorded event took.
- Other details about the event.
- Duration (at time-stamp)
- How long it took the event with all of its children to complete; timestamp is the time at which the event occurred, relative to when the recording started.
- Self time
- How long the event took without any of its children.
- Used Heap Size
- Amount of memory being used by the application when the event was recorded, and the delta (+/-) change in used heap size since the last sampling.
This section lists events that belong to Loading category and their properties.
|Parse HTML||Chrome executed its HTML parsing algorithm.|
|Finish Loading||A network request completed.|
|Receive Data||Data for a request was received. There will be one or more Receive Data events.|
|Receive Response||The initial HTTP response from a request.|
|Send Request||A network request has been sent.|
Loading event properties
- The URL of the requested resource.
- Preview of the requested resource (images only).
- Request Method
- HTTP method used for the request (GET or POST, for example).
- Status Code
- HTTP response code
- MIME Type
- MIME type of the requested resource.
- Encoded Data Length
- Length of requested resource in bytes.
This section lists events that belong to the Scripting category and their properties.
|Animation Frame Fired||A scheduled animation frame fired, and its callback handler invoked.|
|Cancel Animation Frame||A scheduled animation frame was canceled.|
|GC Event||Garbage collection occurred.|
|DOMContentLoaded||The DOMContentLoaded was fired by the browser. This event is fired when all of the page’s DOM content has been loaded and parsed.|
|Evaluate Script||A script was evaluated.|
|Install Timer||A timer was created with setInterval() or setTimeout().|
|Request Animation Frame||A requestAnimationFrame() call scheduled a new frame|
|Remove Timer||A previously created timer was cleared.|
|Time||A script called console.time()|
|Time End||A script calledconsole.timeEnd()|
|Timer Fired||A timer fired that was scheduled with setInterval() or setTimeout().|
|XHR Ready State Change||The ready state of an XMLHTTPRequest changed.|
|XHR Load||An XMLHTTPRequest finished loading.|
Scripting event properties
- Timer ID
- The timer ID.
- The timeout specified by the timer.
- Boolean that specifies if the timer repeats.
- Function Call
- A function that was invoked.
This section lists events that belong to Rendering category and their properties.
|Invalidate layout||The page layout was invalidated by a DOM change.|
|Layout||A page layout was executed.|
|Recalculate style||Chrome recalculated element styles.|
|Scroll||The content of nested view was scrolled.|
Rendering event properties
- Layout invalidated
- For Layout records, the stack trace of the code that caused the layout to be invalidated.
- Nodes that need layout
- For Layout records, the number of nodes that were marked as needing layout before the relayout started. These are normally those nodes that were invalidated by developer code, plus a path upward to relayout root.
- Layout tree size
- For Layout records, the total number of nodes under the relayout root (the node that Chrome starts the relayout).
- Layout scope
- Possible values are "Partial" (the re-layout boundary is a portion of the DOM) or "Whole document".
- Elements affected
- For Recalculate style records, the number of elements affected by a style recalculation.
- Styles invalidated
- For Recalculate style records, provides the stack trace of the code that caused the style invalidation.
This section lists events that belong to Painting category and their properties.
|Composite Layers||Chrome's rendering engine composited image layers.|
|Image Decode||An image resource was decoded.|
|Image Resize||An image was resized from its native dimensions.|
|Paint||Composited layers were painted to a region of the display. Hovering over a Paint record highlights the region of the display that was updated.|
Painting event properties
- For Paint events, the x and y coordinates of the paint rectangle.
- For Paint events, the height and width of the painted region.