For the complete documentation index, see llms.txt. This page is also available as Markdown.

Profiling in the Browser

Learn about how to find and analyze key metrics in the browser tools.


Profiling Web Applications in the Browser

In Optimization Recommendations and Requirements, we stressed the importance of profiling web applications before beginning any optimization. Here, we give an overview of how browser developer tools can be used to profile application metrics

In this section, we use screenshots from Chrome, as it is has the largest user base. However, developer tooling functions similarly across browsers. For instance, Edge and Chrome use the exact same developer tools, with some minor UI differences. Safari has a slightly different collection of tools, but it can be used to achieve similar results. In the next section, we provide platform-specific resources for profiling web applications.

🧰 Accessing Developer Tools

Developer Tools in Chrome

Most profiling utilities are accessible in the "Developer Tools" menu (Web Inspector in Safari). This menu is accessed in a different way on each browser:

Browser
Command

Chrome

Ctrl-Shift-J (Windows) Command-Option-K (Mac)

Edge

F12

Safari

Command-Option-C

Firefox

Ctrl-Shift-K. (Windows) Command-Option-K (Mac)

⏱️ Profiling Application Metrics

The Developer Tools browser menu can be used to access profilers for the core application metrics described in Optimization Recommendations and Requirements. Here, we give an overview of generating profiles with these tools and interpreting the results.

Overview

We recommend enabling the built-in FPS overlay on desktop devices while developing an application. This allows developers to quickly detect if a change has impacted performance, even when not they are not doing optimization work. This helps prevent performance regressions from accidentally getting out to users.

Guide: Enabling the FPS Overlay

Focus the Developer Tools Menu and enter ctrl/cmd + shift + P . This opens a search menu:

Type "show FPS" into the search menu and hit Enter

Observe the FPS counter in the top left corner of the application.

Interpreting Results

  • Average FPS is displayed at the top of the overlay (69.6 FPS in the picture above)

  • Variance in FPS can be determined from the colored bar below the average FPS. Yellow segments represent samples above 60 fps, while red segments represent samples below 60 fps. In the image above, FPS is hovering around 60 fps, so short red segments are interspersed with short yellow segments.

  • In a well-optimized application, all segments will be yellow:

  • In a poorly-optimized application, many segments will be red:

  • GPU memory usage is displayed at the bottom of the overlay. GPU performance typically scales with memory usage. In the image above, there is very little GPU overhead.

Overview

Most optimization work in the browser revolves around generating profiles in the "Performance" tab (Timelines in Safari). In this tab, we can break down how much time is spent each frame on scripting, shaders, and garbage collection (GC). We can also view outlier frames, i.e. frames that last much longer than the average frame, contributing to instability.

Guide: Generating a Performance Profile

Select the Performance tab (Timelines in Safari) and click the "record" button.

If your browser supports memory profiling, be sure to toggle the option. This allows you to analyze garbage collection pauses with more detail.

Developers can enable CPU throttling to approximate performance on less-powerful mobile devices. We recommend selecting "mid-tier mobile", as Chrome normalizes these values across devices.

The performance profiler generates a flame graph, which shows how much time is spent in individual functions in each frame. The functions stack downwards, so the core render function will be near the top, and native calls, JavaScript APIs, and WebGL calls will be at the bottom.

We also see the amount of memory being used during the profile. This typically has a "sawtooth" pattern, as garbage collection will automatically trigger once memory usage reaches a certain level.

Garbage collection appears in the flame graph as either a "Minor GC" or "Major GC" event, corresponding to a partial garbage collection or a full garbage collection, respectively. The differences between minor and major GC are explored in more depth on the v8 blog.

GPU overhead is recorded at the bottom of the profile, but there is relatively little detail provided.

Interpreting results

  • In a well-optimized application, the flamegraph will have a small width relative to the size of the length of the frame. In the screenshot below with mid-tier mobile throttling selected, we spend about 5ms per frame in scripting, leaving plenty of room for GPU overhead. This application can be expected to run at above 60 FPS on most devices:

  • In a poorly-optimized application with the same throttling, we see much more time spent in scripting, over 20 ms in this case. This application will run well below 60 fps, as this does not include time spent on the GPU. Here, we can see a lot of time spent in the "render" function. This suggests that the developer should reduce the number of draw calls in the application.

  • In a well-optimized application, there should be a long time between Minor GC events. To achieve this, developers should reduce temporary allocations, as described in Challenges and Optimization Strategies.

  • A "Major GC" event will correspond to a noticeable freeze in the application. These should be minimized as much as possible. Major garbage collection events can also be avoided by using temporary variables, but often correlate to a major scripting event, such as hundreds of meshes being removed from the scene at once. In these circumstances, it may be better to split up the work across multiple frames with setTimeout, allowing for multiple small GC pauses that are less noticeable to the user.

Overview

It can be challenging to locate the memory allocations that contribute to long garbage collection pauses or application crashes. In many cases, these allocations are split across many different functions and objects, each of which needs to be optimized. To identify these functions and objects, developers can take a "Heap Snapshot", which captures all of the application's allocated memory objects at a given time point and where they are still being used.

Generating a Memory Snapshot

Select the Memory tab in Developer Tools

Click the record button to take a heap snapshot

This generates an overview of how much memory is consumed by your application, and where the majority of memory is allocated. It is important to minimize the amount of temporary "object" and "array" memory used by your application, as this memory contributes the most to garbage collection pauses.

Interpreting Results

Minimizing large objects

Select an object that is utilizing lots of memory. Typically, these will be ArrayBuffers, Meshes, Vectors, other game engine objects, or plain JavaScript arrays like the ArrayBuffer below:

We can then see that the ArrayBuffer is being allocated as matrix transform data for instances of a mesh. Given the large amount of memory being allocated for this matrix, it may make sense to reduce the number of instances rendered by the corresponding mesh, as this could cause a GC pause when it is disposed.

Minimizing large quantities of small objects

In addition to the large ArrayBuffer allocation, we also see a large number of Vector3 objects being allocated (43,363)

Most of these Vector3 objects are in use by the engine, but some of them correspond to temporary variables created in a loop in our experience logic. These temporary variables should ideally be reused, as described in .

Overview

There are three main tools for profiling loading time: the performance profiler, Lighthouse (only available in Chrome and Edge), and the network tab. Lighthouse generates a report on how long the application takes to load

Guide: Profiling Loading Performance

To profile scripting performance while loading, reload the page while recording performance. This generates a performance profile that is identical to the one described in General Performance.

In the generated profile, we can see lots of time being spent decoding textures. This could be reduced by using smaller texture sizes, which take less time to decode, or by merging textures into a single texture atlas.

Guide: Generating Lighthouse Reports

Chrome has built-in tools for analyzing loading time performance in the "Lighthouse" tab.

This gives information on asset download sizes, how long the initial load takes, and how long it takes for the application to come fully interactive. This is useful in determining TTID. TTID roughly corresponds to the "First Contentful Paint" metric. There is not an exact analogue for TTFD, as Lighthouse cannot determine whether or not the canvas is interactive.

In a poorly optimized application, Lighthouse will give information on specific assets to optimize, such as textures, meshes, and code.

Guide: Inspecting Network Downloads

The network tab can be used to inspect the size and timing of network fetches. To profile network activity, open the network tab, and reload the page. Select "Disable Cache" to ensure that everything is downloaded over the network.

Look for assets with large sizes. Here, we may choose to compress the skybox texture even more, as the combined assets are about 6 MB.

📱 Profiling Mobile Devices

There are two main ways to capture mobile performance metrics:

  • directly profiling a connected mobile device

  • emulating a mobile device in the browser

These techniques should be used in combination. Profiling mobile hardware gives more representative data, while emulation can be used to provide a wider range of data points. Crucially, GPU performance does not scale in browser emulators, so frame rate may be higher in the emulator. Emulators should primarily be used to approximate CPU performance across a range of devices and to validate image quality across a range of resolutions.

Prerequisites

  1. Access to an Android Device

  2. Install Android Debug Bridge (ADB) to connect to the android device.

  3. Install Chrome or Edge on your desktop/laptop computer. In Edge, replace chrome:// with edge:// for the following steps.

Connecting to an Android Device via USB

  1. Connect an android device via USB

  2. In a terminal, run adb devices to start the debugging server

  3. Navigate to chrome://inspect/devices and click "inspect" the connected device

  4. This brings up the Developer Tools menu for the connected device. From here, profiling is the same as on a desktop

Generating Native Performance Profiles

  1. In chrome://inspect/devices, select the "trace" option.

  2. If debugging an Android XR device, select Edit categories > check xr.debug

  3. Click record to begin generating a native trace.

Prerequisites

  1. Access to an iOS device

Connecting to an iOS device

  1. Profile the application using safari dev tools.

Emulating a Mobile Device

Open Developer Tools and select the icon in the top left corner that looks like a laptop computer. This enables device emulation, allowing a developer to select from a range of devices to emulate.

Developers can then select a device to emulate in the main browser window, and apply throttling to the CPU. Below, we selected an iPhone 12 Pro with Mid-tier Mobile throttling:

Emulating a WebXR Device

For WebXR Emulation, install the Meta Immersive Web Emulator. It is supported on Chrome and Edge. This allows developers to profile immersive experiences more accurately, and gives tools for manipulating the XR headset and controllers:


Profiling Resources for Web Browsers and Devices

Beyond the overview we have provided, each browser provides detailed guides for debugging and profiling applications. Here we provide lists of resources for each major browser, as well as resources for connecting to mobile devices from Chrome and Safari.

Platform Support

🖥️ Desktop & 📱 Mobile

Core Developer Tools

Additional Tooling

Mobile Tooling

Platform Support

🖥️ Desktop

Core Developer Tools

Additional Tooling

Mobile Tooling

Platform Support

Desktop & 📱 Mobile

Core Developer Tools

Mobile Tooling

Last updated

Was this helpful?