# Profiling in the Browser

***

## Profiling Web Applications in the Browser

In [optimization-recommendations-and-requirements](https://docs.viverse.com/optimization/optimization-recommendations-and-requirements "mention"), 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&#x20;

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.

### :toolbox: Accessing Developer Tools

<figure><img src="https://4103825490-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfftOtn5BNeroGvlbe5W9%2Fuploads%2FdvPUy0YPsMgqxckN5Wxa%2FScreenshot%202025-08-24%20at%204.36.53%E2%80%AFPM.png?alt=media&#x26;token=34ff0d36-bd00-4836-8123-74ea7c3bcfed" alt=""><figcaption><p>Developer Tools in Chrome</p></figcaption></figure>

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  | <p>Ctrl-Shift-J (Windows)<br>Command-Option-K (Mac)</p>  |
| Edge    | F12                                                      |
| Safari  | Command-Option-C                                         |
| Firefox | <p>Ctrl-Shift-K. (Windows)<br>Command-Option-K (Mac)</p> |

### :stopwatch: 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](https://docs.viverse.com/optimization/optimization-recommendations-and-requirements "mention"). Here, we give an overview of generating profiles with these tools and interpreting the results.

{% tabs %}
{% tab title="FPS" %}

#### 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.&#x20;

#### Guide: Enabling the FPS Overlay

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

<figure><img src="https://4103825490-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfftOtn5BNeroGvlbe5W9%2Fuploads%2FtK2ja53M9HQvH21sEG0C%2FScreenshot%202025-08-24%20at%204.39.24%E2%80%AFPM.png?alt=media&#x26;token=2c2c7ad8-d2fc-4994-bfdd-c7d03a76d244" alt=""><figcaption></figcaption></figure>

Type "show FPS" into the search menu and hit `Enter`\
\
\ <br>

<figure><img src="https://4103825490-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfftOtn5BNeroGvlbe5W9%2Fuploads%2Fqe6Pkg0gxEv3JDonxYuU%2FScreenshot%202025-08-22%20at%205.02.03%E2%80%AFPM.png?alt=media&#x26;token=ebe384da-8606-4b14-9f69-c7e3fab776de" alt=""><figcaption></figcaption></figure>

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

<figure><img src="https://4103825490-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfftOtn5BNeroGvlbe5W9%2Fuploads%2FvGP5MDo8VXGRl7UJDh2X%2FScreenshot%202025-08-25%20at%2011.45.42%E2%80%AFAM.png?alt=media&#x26;token=03353947-13ad-463b-8d25-aff6f9110506" alt=""><figcaption></figcaption></figure>

#### 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.&#x20;
* In a well-optimized application, all segments will be yellow:&#x20;

  <figure><img src="https://4103825490-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfftOtn5BNeroGvlbe5W9%2Fuploads%2FdDPJtlJEQAkQRsjSdAym%2FScreenshot%202025-08-25%20at%2011.49.24%E2%80%AFAM.png?alt=media&#x26;token=d80eda46-e8dc-49bf-a688-3e359c65d32a" alt=""><figcaption></figcaption></figure>
* In a poorly-optimized application, many segments will be red:&#x20;

  <figure><img src="https://4103825490-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfftOtn5BNeroGvlbe5W9%2Fuploads%2F47IKQtjW27h725Oth9Xf%2FScreenshot%202025-08-25%20at%2011.52.14%E2%80%AFAM.png?alt=media&#x26;token=d878b073-6143-46a1-9145-6fd05474b7b8" alt=""><figcaption></figcaption></figure>
* 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.&#x20;
  {% endtab %}

{% tab title="General Performance" %}

#### 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.&#x20;

<figure><img src="https://4103825490-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfftOtn5BNeroGvlbe5W9%2Fuploads%2FulpPu1nuhK9ds466rXmX%2FScreenshot%202025-08-24%20at%204.45.31%E2%80%AFPM.png?alt=media&#x26;token=c73ea16b-8995-4242-a6ef-36cb80eab154" alt=""><figcaption></figcaption></figure>

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

<figure><img src="https://4103825490-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfftOtn5BNeroGvlbe5W9%2Fuploads%2F5mJK41Mb8oyYqGk9OqH4%2FScreenshot%202025-08-22%20at%204.46.30%E2%80%AFPM.png?alt=media&#x26;token=57df1270-c2f2-427b-9b4c-f28ba78db93f" alt=""><figcaption></figcaption></figure>

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.

<figure><img src="https://4103825490-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfftOtn5BNeroGvlbe5W9%2Fuploads%2Fo0DFQVi6IRw8glOoy5me%2FScreenshot%202025-08-25%20at%2012.00.47%E2%80%AFPM.png?alt=media&#x26;token=5b6896c3-b8a0-41ba-9806-884d0eac3567" alt=""><figcaption></figcaption></figure>

The performance profiler generates a [flame graph](https://queue.acm.org/detail.cfm?id=2927301), 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.

<figure><img src="https://4103825490-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfftOtn5BNeroGvlbe5W9%2Fuploads%2FN0asV6FG8icHQ7CMDZvY%2FScreenshot%202025-08-21%20at%204.29.56%E2%80%AFPM.png?alt=media&#x26;token=d9e131e9-45ea-40c2-ba45-98f60f37bd39" alt=""><figcaption></figcaption></figure>

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.

<figure><img src="https://4103825490-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfftOtn5BNeroGvlbe5W9%2Fuploads%2Fwzgvtvg1ZTy1unLTQzaw%2FScreenshot%202025-08-25%20at%2012.21.51%E2%80%AFPM.png?alt=media&#x26;token=3a9e9638-890e-46f1-b792-4a3305fdc7f6" alt=""><figcaption></figcaption></figure>

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](https://v8.dev/blog/trash-talk).

<figure><img src="https://4103825490-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfftOtn5BNeroGvlbe5W9%2Fuploads%2FC7DlWBzCJLlJdCaW7IvD%2FScreenshot%202025-08-25%20at%2012.26.09%E2%80%AFPM.png?alt=media&#x26;token=455c4e7b-d0fe-4121-a7d2-dcdc45acb081" alt=""><figcaption></figcaption></figure>

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

<figure><img src="https://4103825490-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfftOtn5BNeroGvlbe5W9%2Fuploads%2FaTvi94cki3rMSxcOHP49%2FScreenshot%202025-08-25%20at%2012.39.03%E2%80%AFPM.png?alt=media&#x26;token=c509582c-6d90-442f-adce-b9ffb3f8c672" alt=""><figcaption></figcaption></figure>

#### 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:&#x20;

  <figure><img src="https://4103825490-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfftOtn5BNeroGvlbe5W9%2Fuploads%2Fez5WAKNjGlxtGfFQ9fqq%2FScreenshot%202025-08-25%20at%2011.57.39%E2%80%AFAM.png?alt=media&#x26;token=1f1109cc-a0bf-43e4-90eb-ff55406ba1f3" alt="" width="375"><figcaption></figcaption></figure>
* 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.&#x20;

<figure><img src="https://4103825490-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfftOtn5BNeroGvlbe5W9%2Fuploads%2F9LxsfIAVmPuAYvyFiJLb%2FScreenshot%202025-08-25%20at%2012.05.59%E2%80%AFPM.png?alt=media&#x26;token=e81952bb-d92c-4957-b2a0-9b9c80d8e092" alt="" width="323"><figcaption></figcaption></figure>

* 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](https://docs.viverse.com/optimization/challenges-and-optimization-strategies "mention").&#x20;
* 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](https://developer.mozilla.org/en-US/docs/Web/API/Window/setTimeout), allowing for multiple small GC pauses that are less noticeable to the user.
  {% endtab %}

{% tab title="Memory Usage" %}

#### 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

<figure><img src="https://4103825490-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfftOtn5BNeroGvlbe5W9%2Fuploads%2FmPDPzBQnD1N1lGUDko73%2FScreenshot%202025-08-22%20at%204.47.47%E2%80%AFPM.png?alt=media&#x26;token=420d1843-f850-4265-8031-ef6d9e0ed70e" alt=""><figcaption></figcaption></figure>

Click the record button to take a heap snapshot

<figure><img src="https://4103825490-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfftOtn5BNeroGvlbe5W9%2Fuploads%2FJs1YtdrO7A0VlzMMgtmK%2FScreenshot%202025-08-24%20at%204.41.54%E2%80%AFPM.png?alt=media&#x26;token=6f239221-cf6e-4a90-a031-6cd32cf3db14" alt=""><figcaption></figcaption></figure>

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.

<figure><img src="https://4103825490-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfftOtn5BNeroGvlbe5W9%2Fuploads%2FheqyzSFyQmtzKorKv7L3%2FScreenshot%202025-08-22%20at%204.47.20%E2%80%AFPM.png?alt=media&#x26;token=96f6fe04-9e35-4fb9-8497-3b3f5308e2eb" alt=""><figcaption></figcaption></figure>

#### 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:

<figure><img src="https://4103825490-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfftOtn5BNeroGvlbe5W9%2Fuploads%2FXo41DIwyyLw03tR2GcjK%2FScreenshot%202025-08-25%20at%2012.54.58%E2%80%AFPM.png?alt=media&#x26;token=bfaf4939-7e77-4f2e-8504-a3c038d9a56b" alt=""><figcaption></figcaption></figure>

<figure><img src="https://4103825490-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfftOtn5BNeroGvlbe5W9%2Fuploads%2F55KToKDfEx3ONKxMJpG1%2FScreenshot%202025-08-25%20at%2012.46.27%E2%80%AFPM.png?alt=media&#x26;token=2d2abb5a-1d1a-42a1-bef9-3cabf4ed0cc3" alt=""><figcaption></figcaption></figure>

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.

<figure><img src="https://4103825490-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfftOtn5BNeroGvlbe5W9%2Fuploads%2FNNWKEch99FNyNo2rPJQI%2FScreenshot%202025-08-25%20at%2012.52.37%E2%80%AFPM.png?alt=media&#x26;token=27321c8b-b722-4bb1-af85-07e700e2a0c6" alt=""><figcaption></figcaption></figure>

**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)

<figure><img src="https://4103825490-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfftOtn5BNeroGvlbe5W9%2Fuploads%2FF9uMsvNhNv0EvTOoFs1K%2FScreenshot%202025-08-25%20at%201.01.44%E2%80%AFPM.png?alt=media&#x26;token=e6faff46-c3a2-4380-9daa-e5d4e34c9f59" alt=""><figcaption></figcaption></figure>

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 [Broken link](https://docs.viverse.com/optimization/broken-reference "mention").
{% endtab %}

{% tab title="Loading Time" %}

#### 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](#general-performance "mention").

<figure><img src="https://4103825490-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfftOtn5BNeroGvlbe5W9%2Fuploads%2F81b6nAfny8DIeg9oCmM6%2FScreenshot%202025-08-22%20at%204.49.15%E2%80%AFPM.png?alt=media&#x26;token=e15cf7b8-1530-4e25-b13f-f9796d1f0bda" alt=""><figcaption></figcaption></figure>

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.

<figure><img src="https://4103825490-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfftOtn5BNeroGvlbe5W9%2Fuploads%2Fc56OClxMnO5SjlUwcMNO%2FScreenshot%202025-08-25%20at%201.20.04%E2%80%AFPM.png?alt=media&#x26;token=a51ce4cb-b2ab-4aab-ab44-f27fe79439a4" alt="" width="353"><figcaption></figcaption></figure>

#### Guide: Generating Lighthouse Reports

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

<figure><img src="https://4103825490-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfftOtn5BNeroGvlbe5W9%2Fuploads%2FT9VaKesZ4RaIQHZGxUav%2FScreenshot%202025-08-22%20at%204.48.26%E2%80%AFPM.png?alt=media&#x26;token=84f72fe4-eafc-4b02-9fee-4ffb9ede8ad4" alt=""><figcaption></figcaption></figure>

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.

<figure><img src="https://4103825490-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfftOtn5BNeroGvlbe5W9%2Fuploads%2F6dpEWkRdvpLenLmeNaXA%2FScreenshot%202025-08-24%20at%204.50.16%E2%80%AFPM.png?alt=media&#x26;token=a4296061-8815-4ee2-916a-ddf968e0c5b6" alt=""><figcaption></figcaption></figure>

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

<figure><img src="https://4103825490-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfftOtn5BNeroGvlbe5W9%2Fuploads%2FIA8jf5tYyJO03JN0OTiv%2FScreenshot%202025-08-25%20at%201.14.09%E2%80%AFPM.png?alt=media&#x26;token=e2a5e6c4-454f-45c8-8c52-c782a9a98ee8" alt=""><figcaption></figcaption></figure>

<figure><img src="https://4103825490-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfftOtn5BNeroGvlbe5W9%2Fuploads%2Fqrw3s7dphTXxCW6IjVZY%2FScreenshot%202025-08-25%20at%201.13.57%E2%80%AFPM.png?alt=media&#x26;token=850e1eb1-bd02-4eb8-8c41-a3fbeb3dd684" alt=""><figcaption></figcaption></figure>

#### 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.

<figure><img src="https://4103825490-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfftOtn5BNeroGvlbe5W9%2Fuploads%2FLpHrnQTF8UkNog7PlCne%2FScreenshot%202025-08-25%20at%201.18.52%E2%80%AFPM.png?alt=media&#x26;token=4635770f-3d69-4d15-b8af-0330b21d754d" alt=""><figcaption></figcaption></figure>

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.

<figure><img src="https://4103825490-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfftOtn5BNeroGvlbe5W9%2Fuploads%2FcSSgfyqocRiw3xRZRu7D%2FScreenshot%202025-08-25%20at%201.16.46%E2%80%AFPM.png?alt=media&#x26;token=b452d64c-4949-4410-b34f-2503625db188" alt=""><figcaption></figcaption></figure>
{% endtab %}
{% endtabs %}

### :mobile\_phone: Profiling Mobile Devices

There are two main ways to capture mobile performance metrics:&#x20;

* 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.

{% tabs %}
{% tab title="Android" %}

#### Prerequisites

1. Access to an Android Device
2. Install Android Debug Bridge ([ADB](https://developer.android.com/tools/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.
   {% endtab %}

{% tab title="iOS" %}

#### Prerequisites

1. Access to an iOS device
2. [Enable inpsecting safari on the iOS Device](https://developer.apple.com/documentation/safari-developer-tools/inspecting-ios#Enabling-inspecting-your-device-from-a-connected-Mac)

#### Connecting to an iOS device

1. [Connect to the device over WiFi or USB](https://developer.apple.com/documentation/safari-developer-tools/inspecting-ios#Enabling-inspecting-your-device-from-a-connected-Mac)
2. [Open Safari > Develop > Your Device > Your Application](https://developer.apple.com/documentation/safari-developer-tools/inspecting-ios#Inspecting-a-webpage)
3. Profile the application using safari dev tools.
   {% endtab %}

{% tab title="Mobile Device Emulation" %}

#### 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.

<figure><img src="https://4103825490-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfftOtn5BNeroGvlbe5W9%2Fuploads%2FQcarLEqkJucZKwW7Xyz7%2FScreenshot%202025-08-25%20at%201.22.43%E2%80%AFPM.png?alt=media&#x26;token=fc5aadbb-fe51-4bee-a418-04af02d42d91" alt=""><figcaption></figcaption></figure>

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:

<figure><img src="https://4103825490-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfftOtn5BNeroGvlbe5W9%2Fuploads%2Fm6SdmPaJHFXALY5yomG6%2FScreenshot%202025-08-25%20at%201.27.03%E2%80%AFPM.png?alt=media&#x26;token=868a0918-df81-47ad-90cd-848220b62371" alt=""><figcaption></figcaption></figure>
{% endtab %}

{% tab title="WebXR Emulation" %}

#### Emulating a WebXR Device

For WebXR Emulation, install the [Meta Immersive Web Emulator](https://developers.meta.com/horizon/blog/webxr-development-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:<br>

<figure><img src="https://4103825490-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfftOtn5BNeroGvlbe5W9%2Fuploads%2F8GNMXeJoUfHcYD6LG2yi%2FScreenshot%202025-08-25%20at%201.29.01%E2%80%AFPM.png?alt=media&#x26;token=094ccb71-58d2-47d1-a3c6-0d089e9e03df" alt=""><figcaption></figcaption></figure>
{% endtab %}
{% endtabs %}

***

## 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.

{% tabs %}
{% tab title="Chrome" %}

#### Platform Support

:desktop: Desktop & :mobile\_phone: Mobile

#### Core Developer Tools

* [Performance Profiling](https://developer.chrome.com/docs/devtools/performance/overview)
* [Debugger](https://developer.chrome.com/docs/devtools/javascript)
* [Network Profiling](https://developer.chrome.com/docs/devtools/network/overview)
* [Memory Profiling](https://developer.chrome.com/docs/devtools/memory)

#### Additional Tooling

* [Tracing Tool](https://www.chromium.org/developers/how-tos/trace-event-profiling-tool/): Provides more introspection into the native side of chrome, showing JavaScript engine traces and GPU tracing.
* [Lighthouse](https://developer.chrome.com/docs/devtools/lighthouse): Tools for optimizing app start time and file size.
* [Immersive Web Emulator Plugin](https://chromewebstore.google.com/detail/immersive-web-emulator/cgffilbpcibhmcfbgggfhfolhkfbhmik?pli=1): emulate XR devices in Chrome Developer Tools
* Display [frame rate](https://devtoolstips.org/tips/en/display-current-framerate/)
* [WebAssembly debugger](https://developer.chrome.com/docs/devtools/wasm)

#### Mobile Tooling

* [Remote Debugging](https://developer.chrome.com/docs/devtools/remote-debugging/local-server)
* [Device Emulator](https://developer.chrome.com/docs/devtools/device-mode/)
  {% endtab %}

{% tab title="Edge" %}

#### Platform Support

&#x20;:desktop: Desktop

#### Core Developer Tools

* [Performance Profiling](https://learn.microsoft.com/en-us/microsoft-edge/devtools/performance/overview)
* [Debugger](https://learn.microsoft.com/en-us/microsoft-edge/devtools/javascript/)
* [Network Profiling](https://learn.microsoft.com/en-us/microsoft-edge/devtools/network/)
* [Memory Profiling](https://learn.microsoft.com/en-us/microsoft-edge/devtools/memory-problems/)

#### Additional Tooling

* [Immersive Web Emulator Plugin](https://microsoftedge.microsoft.com/addons/detail/immersive-web-emulator/hhlkbhldhffpeibcfggfndbkfohndamj): emulate XR devices in Edge Developer Tools

#### Mobile Tooling

* [Device Emulator](https://learn.microsoft.com/en-us/microsoft-edge/devtools/device-mode/)
  {% endtab %}

{% tab title="Safari" %}

#### Platform Support

Desktop & :mobile\_phone: Mobile

#### Core Developer Tools

* [Tools Overview](https://developer.apple.com/documentation/safari-developer-tools/web-inspector)
* [Timelines](https://webkit.org/web-inspector/timelines-tab/) (Scripting and Memory profiler)
* [Debugger](https://webkit.org/web-inspector/sources-tab/)
* [Network Profiler](https://webkit.org/web-inspector/network-tab/)

#### Mobile Tooling

* [Inspecting iOS devices](https://developer.apple.com/documentation/safari-developer-tools/inspecting-ios)
  {% endtab %}
  {% endtabs %}
