profile-viewer 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/dist/022efb839d22fa54a716.svg +28 -0
- data/dist/0c510afd6169a0a83f97.svg +14 -0
- data/dist/0d5cf282780cd1a5ec64.svg +8 -0
- data/dist/119.cc58ce313e67f80f50f3.bundle.js +2 -0
- data/dist/119.cc58ce313e67f80f50f3.bundle.js.map +1 -0
- data/dist/11c5dca6d97c9e10e5b7.svg +9 -0
- data/dist/131.c21d348572deab4ece66.bundle.js +2 -0
- data/dist/131.c21d348572deab4ece66.bundle.js.map +1 -0
- data/dist/18e7fdd45099134897d2.svg +8 -0
- data/dist/2d4b477bc424d35a0245.svg +25 -0
- data/dist/2e43ad991eb141fc017f.svg +9 -0
- data/dist/2ea5b50b7361e6de561c.svg +11 -0
- data/dist/308.4d236ce7e6451807cb54.bundle.js +2 -0
- data/dist/308.4d236ce7e6451807cb54.bundle.js.map +1 -0
- data/dist/31fe933f3a12be1aa7f3.svg +4 -0
- data/dist/390aa266f451c1005f61.svg +10 -0
- data/dist/3c3fda7c08bcc9544c64.svg +6 -0
- data/dist/4260d5db8309a6f83637.svg +10 -0
- data/dist/4536fd0738f36c3463bc.svg +1 -0
- data/dist/490065792b7e903c9f3e.svg +6 -0
- data/dist/49da6a2153f62ef73d17.svg +7 -0
- data/dist/4d26f0e38c22eedde178.jpg +0 -0
- data/dist/4ecb077d8715f89c0f87.svg +13 -0
- data/dist/524e896f487119a0b832.svg +13 -0
- data/dist/58c5415e952fb6dddd6b.png +0 -0
- data/dist/6bd0589a27236471fdab.svg +4 -0
- data/dist/6c6b49af3a86dfdd44e6.svg +4 -0
- data/dist/6c8063be3afa1d95c902.svg +3 -0
- data/dist/71730566d6c47ffdc965.svg +12 -0
- data/dist/7273fadce89da05535e5.svg +4 -0
- data/dist/731673c749e57bf6f544.svg +13 -0
- data/dist/76e5b29823c9fd62d90d.svg +3 -0
- data/dist/7853c71223701f30d495.svg +19 -0
- data/dist/79856ce399cb305fafb8.svg +19 -0
- data/dist/79eaad4fc0c398100809.svg +6 -0
- data/dist/7c7ac3c7df370340cfd2.svg +7 -0
- data/dist/7e3ac9afb25cfe809520.svg +1 -0
- data/dist/81762b0b1aacd3686a6b.svg +12 -0
- data/dist/86e81402ef76d28ff55f.svg +15 -0
- data/dist/8aae7b979b04407f71a4.svg +3 -0
- data/dist/8b8b909e42722172d494.svg +7 -0
- data/dist/8dab2a6ba757bcc6e9a5.svg +3 -0
- data/dist/9.071a712ea648c8b30416.bundle.js +2 -0
- data/dist/9.071a712ea648c8b30416.bundle.js.map +1 -0
- data/dist/9103e94f1d34c15d44be.svg +6 -0
- data/dist/914.b9bc213d93173ce6b0cb.bundle.js +2 -0
- data/dist/914.b9bc213d93173ce6b0cb.bundle.js.map +1 -0
- data/dist/9a7bd6ec36312a2baa7e.svg +1 -0
- data/dist/9d858d1a3ab57f8ee2e1.svg +4 -0
- data/dist/9eb1fab2684d1e1f0e26.svg +13 -0
- data/dist/_headers +37 -0
- data/dist/_redirects +2 -0
- data/dist/a3196e840709b18a3119.svg +1 -0
- data/dist/aa867391c311267af5a9.svg +4 -0
- data/dist/acb8393f3fb9c59b15c9.svg +20 -0
- data/dist/ad13da76642d8099fe70.module.wasm +0 -0
- data/dist/b45b29da558efa211628.jpg +0 -0
- data/dist/b5698a02eef37ce29146.svg +10 -0
- data/dist/b805360fcc91834556c9.svg +4 -0
- data/dist/before-load.js +1 -0
- data/dist/c3432220f657733ed05f.svg +10 -0
- data/dist/ca2af827049e9039ef9c.svg +8 -0
- data/dist/contribute.json +37 -0
- data/dist/d09537c705fb0878eb63.svg +4 -0
- data/dist/d9c199b3e3e469cc5713.svg +10 -0
- data/dist/da1f21c60c7217745dd8.svg +1 -0
- data/dist/docs/README.md +7 -0
- data/dist/docs/_navbar.md +3 -0
- data/dist/docs/_sidebar.md +27 -0
- data/dist/docs/advanced-topics.md +9 -0
- data/dist/docs/bunny-2.md +78 -0
- data/dist/docs/bunny.md +281 -0
- data/dist/docs/case-studies.md +5 -0
- data/dist/docs/css/style-overrides.css +160 -0
- data/dist/docs/css/vue_v4.12.2.min.css +858 -0
- data/dist/docs/gitpod.md +39 -0
- data/dist/docs/guide-android-profiling.md +46 -0
- data/dist/docs/guide-filtering-call-trees.md +87 -0
- data/dist/docs/guide-getting-started.md +115 -0
- data/dist/docs/guide-perf-profiling.md +76 -0
- data/dist/docs/guide-profiler-fundamentals.md +33 -0
- data/dist/docs/guide-profiling-android-directly-on-device.md +34 -0
- data/dist/docs/guide-profiling-firefox-android.md +7 -0
- data/dist/docs/guide-remote-profiling.md +90 -0
- data/dist/docs/guide-removing-profiler.md +4 -0
- data/dist/docs/guide-stack-samples-and-call-trees.md +57 -0
- data/dist/docs/guide-startup-shutdown.md +108 -0
- data/dist/docs/guide-ui-tour-panels.md +95 -0
- data/dist/docs/guide-ui-tour-timeline.md +76 -0
- data/dist/docs/images/about-debugging-remote-profiling-panel.png +0 -0
- data/dist/docs/images/about-debugging-remote.png +0 -0
- data/dist/docs/images/about-url.png +0 -0
- data/dist/docs/images/allocation-calltree-2019-12-11.png +0 -0
- data/dist/docs/images/allocation-feature.png +0 -0
- data/dist/docs/images/allocation-flame-graph-2019-12-11.png +0 -0
- data/dist/docs/images/allocation-js.png +0 -0
- data/dist/docs/images/allocation-track.png +0 -0
- data/dist/docs/images/bunny-analysis/bunny.png +0 -0
- data/dist/docs/images/bunny-analysis/clone-flame-content.png +0 -0
- data/dist/docs/images/bunny-analysis/clone-flame-worker.png +0 -0
- data/dist/docs/images/bunny-analysis/clone-thread-list.png +0 -0
- data/dist/docs/images/bunny-analysis/fillstyle-thread-list-measure.png +0 -0
- data/dist/docs/images/bunny-analysis/fillstyle-thread-list.png +0 -0
- data/dist/docs/images/bunny-analysis/flame-graph-content.png +0 -0
- data/dist/docs/images/bunny-analysis/flame-graph-set-fillstyle.png +0 -0
- data/dist/docs/images/bunny-analysis/flame-graph-worker.png +0 -0
- data/dist/docs/images/bunny-analysis/focus-subtree.png +0 -0
- data/dist/docs/images/bunny-analysis/threads-list-measure.png +0 -0
- data/dist/docs/images/bunny-analysis/threads-list.png +0 -0
- data/dist/docs/images/bunny-analysis/threads-parallel.png +0 -0
- data/dist/docs/images/bunny-analysis/threads-sync.png +0 -0
- data/dist/docs/images/bunny-analysis/threads-work-parallel.png +0 -0
- data/dist/docs/images/bunny-analysis/threads-work-sync.png +0 -0
- data/dist/docs/images/call-tree-running-time.svg +82 -0
- data/dist/docs/images/call-tree-self-time.svg +82 -0
- data/dist/docs/images/call-tree.svg +131 -0
- data/dist/docs/images/favicon.svg +4 -0
- data/dist/docs/images/filter-search.svg +78 -0
- data/dist/docs/images/getting-started-delete-profile.png +0 -0
- data/dist/docs/images/getting-started-devtools-panel.png +0 -0
- data/dist/docs/images/getting-started-enable-popup.png +0 -0
- data/dist/docs/images/getting-started-list-uploaded-profiles.png +0 -0
- data/dist/docs/images/getting-started-naming-profiles.png +0 -0
- data/dist/docs/images/getting-started-popup.png +0 -0
- data/dist/docs/images/getting-started-upload-permalink.webm +0 -0
- data/dist/docs/images/getting-started-upload.png +0 -0
- data/dist/docs/images/getting-started-use-icon.webm +0 -0
- data/dist/docs/images/getting-started-use-popup.webm +0 -0
- data/dist/docs/images/implementation-2022-06-16.png +0 -0
- data/dist/docs/images/implementation-filter.svg +101 -0
- data/dist/docs/images/interval-2020-05.png +0 -0
- data/dist/docs/images/invert-2022-06-16.png +0 -0
- data/dist/docs/images/invert-after.svg +161 -0
- data/dist/docs/images/invert-before.svg +144 -0
- data/dist/docs/images/invert-call-tree.svg +113 -0
- data/dist/docs/images/ipc-messages-feature.png +0 -0
- data/dist/docs/images/ipc-messages-io-threads.png +0 -0
- data/dist/docs/images/ipc-messages-popup.png +0 -0
- data/dist/docs/images/popup.png +0 -0
- data/dist/docs/images/qr-gve-nightly.gif +0 -0
- data/dist/docs/images/qr-reference-browser-nightly.gif +0 -0
- data/dist/docs/images/samples.svg +116 -0
- data/dist/docs/images/screenshot-2022-04-25.png +0 -0
- data/dist/docs/images/search-2022-06-16.png +0 -0
- data/dist/docs/images/secret-menu-toast.png +0 -0
- data/dist/docs/images/settings-menu.png +0 -0
- data/dist/docs/images/simple-call-tree-self-time.svg +41 -0
- data/dist/docs/images/simple-call-tree.svg +41 -0
- data/dist/docs/images/simple-stacks-self-time.svg +96 -0
- data/dist/docs/images/simple-stacks.svg +118 -0
- data/dist/docs/images/start-profiler.png +0 -0
- data/dist/docs/images/transform-collapse-direct-recursion.svg +47 -0
- data/dist/docs/images/transform-collapse-resource.svg +83 -0
- data/dist/docs/images/transform-focus-function.svg +81 -0
- data/dist/docs/images/transform-focus-node.svg +86 -0
- data/dist/docs/images/transform-merge-function.svg +95 -0
- data/dist/docs/images/transform-merge-node.svg +96 -0
- data/dist/docs/images/transforms-2022-06-16.png +0 -0
- data/dist/docs/images/ui-tour-activity-graph.png +0 -0
- data/dist/docs/images/ui-tour-panels-call-tree.png +0 -0
- data/dist/docs/images/ui-tour-panels-flame-graph.png +0 -0
- data/dist/docs/images/ui-tour-panels-marker-chart.png +0 -0
- data/dist/docs/images/ui-tour-panels-network-chart.png +0 -0
- data/dist/docs/images/ui-tour-panels-stack-chart.png +0 -0
- data/dist/docs/images/ui-tour-panels.png +0 -0
- data/dist/docs/images/ui-tour-ranges.png +0 -0
- data/dist/docs/images/ui-tour-selection.webm +0 -0
- data/dist/docs/images/ui-tour-timeline-markers.png +0 -0
- data/dist/docs/images/ui-tour-timeline-memory.png +0 -0
- data/dist/docs/images/ui-tour-timeline-network.png +0 -0
- data/dist/docs/images/ui-tour-timeline-screenshots.png +0 -0
- data/dist/docs/images/ui-tour-timeline-track-selection.png +0 -0
- data/dist/docs/images/ui-tour-timeline.png +0 -0
- data/dist/docs/index.html +21 -0
- data/dist/docs/ipc-messages.md +44 -0
- data/dist/docs/js/docsify_v4.12.2+.min.js +1 -0
- data/dist/docs/js/ga_v4.12.2.min.js +1 -0
- data/dist/docs/js/init.js +1 -0
- data/dist/docs/js/search_v4.12.2.min.js +1 -0
- data/dist/docs/memory-allocations.md +70 -0
- data/dist/docs/videos-call-tree-1.md +5 -0
- data/dist/docs/videos-call-tree-2.md +5 -0
- data/dist/docs/videos-call-tree-3.md +5 -0
- data/dist/docs/videos-intro.md +7 -0
- data/dist/docs/videos-samples-markers.md +5 -0
- data/dist/docs/videos-threads.md +5 -0
- data/dist/docs/videos.md +32 -0
- data/dist/e4ed50222911c5af9a32.svg +12 -0
- data/dist/e70722c0fe0ac3d4227b.svg +10 -0
- data/dist/f0599659345cf76717cd.svg +4 -0
- data/dist/f8e25c2ebeb0a0725a9e.svg +12 -0
- data/dist/favicon.png +0 -0
- data/dist/fcb532a05dd4b09c2d08.svg +10 -0
- data/dist/fd040fb5f4e7a515bb3c.svg +15 -0
- data/dist/index.html +1 -0
- data/dist/locales/README.md +26 -0
- data/dist/locales/be/app.ftl +1003 -0
- data/dist/locales/de/app.ftl +994 -0
- data/dist/locales/el/app.ftl +1013 -0
- data/dist/locales/en-GB/app.ftl +1018 -0
- data/dist/locales/en-US/app.ftl +1125 -0
- data/dist/locales/es-CL/app.ftl +948 -0
- data/dist/locales/fr/app.ftl +942 -0
- data/dist/locales/fy-NL/app.ftl +1018 -0
- data/dist/locales/ia/app.ftl +1007 -0
- data/dist/locales/it/app.ftl +936 -0
- data/dist/locales/kab/app.ftl +557 -0
- data/dist/locales/nl/app.ftl +1018 -0
- data/dist/locales/pt-BR/app.ftl +947 -0
- data/dist/locales/ru/app.ftl +1032 -0
- data/dist/locales/sv-SE/app.ftl +1013 -0
- data/dist/locales/uk/app.ftl +1019 -0
- data/dist/locales/zh-CN/app.ftl +931 -0
- data/dist/locales/zh-TW/app.ftl +930 -0
- data/dist/main.8208fda2d35ddbe38d55.bundle.js +199 -0
- data/dist/main.8208fda2d35ddbe38d55.bundle.js.LICENSE.txt +92 -0
- data/dist/main.8208fda2d35ddbe38d55.bundle.js.map +1 -0
- data/dist/photon/31fe933f3a12be1aa7f3.svg +4 -0
- data/dist/photon/49da6a2153f62ef73d17.svg +7 -0
- data/dist/photon/6bd0589a27236471fdab.svg +4 -0
- data/dist/photon/6c8063be3afa1d95c902.svg +3 -0
- data/dist/photon/76e5b29823c9fd62d90d.svg +3 -0
- data/dist/photon/8aae7b979b04407f71a4.svg +3 -0
- data/dist/photon/8dab2a6ba757bcc6e9a5.svg +3 -0
- data/dist/photon/9103e94f1d34c15d44be.svg +6 -0
- data/dist/photon/aa867391c311267af5a9.svg +4 -0
- data/dist/photon/f0599659345cf76717cd.svg +4 -0
- data/dist/photon/index.html +214 -0
- data/dist/photon/main.8c8260452e7439ec6df9.bundle.js +2 -0
- data/dist/photon/main.8c8260452e7439ec6df9.bundle.js.map +1 -0
- data/dist/service-worker-compat.js +1 -0
- data/dist/sw.js +2 -0
- data/dist/sw.js.map +1 -0
- data/dist/workbox-27b29e6f.js +2 -0
- data/dist/workbox-27b29e6f.js.map +1 -0
- data/dist/zee-worker.js +1 -0
- data/ruby-bin/profile-viewer +87 -0
- metadata +281 -0
data/dist/docs/gitpod.md
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# Setting up profiler on gitpod
|
2
|
+
|
3
|
+
Instead of configuring a local setup, you can also use [gitpod](https://www.gitpod.io/), an online continuous development environment with minimum setup.
|
4
|
+
Click the link below. An automatic workspace will be created.
|
5
|
+
|
6
|
+
[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/firefox-devtools/profiler)
|
7
|
+
|
8
|
+
## Authorize with github
|
9
|
+
|
10
|
+
If you are using gitpod for the first time, you will have to authorize access to your GitHub account.This is necessary so you can access your data from within Gitpod.
|
11
|
+
|
12
|
+
To authorize access, click your avatar/profile picture at the top right hand section of the setup. A dropdown menu will be displayed. In the dropdown menu, click `Open Access Control`. It will open Access Control page from where you can check the checkboxes and click update.
|
13
|
+
|
14
|
+
## Open the profiler UI in your web browser
|
15
|
+
|
16
|
+
A popup box, `Open Ports View`, also appears at the bottom right hand section of the setup with the message `A service is available on port 4242`. You can click `Open Browser` which will open profiler UI, [profiler.firefox.com](https://profiler.firefox.com/), for your setup in a separate tab. If you have closed `Open Ports View`, you can display it by clicking `PORTS` at the right hand section of the bottom bar.
|
17
|
+
|
18
|
+
## Load custom profiles
|
19
|
+
|
20
|
+
If you want to load profiles for development, you can follow the steps described in [Loading in profiles for development](../CONTRIBUTING.md#loading-in-profiles-for-development) section.
|
21
|
+
|
22
|
+
## Advanced usage
|
23
|
+
|
24
|
+
As an alternative to following the link above, you can also login using your gitHub account and then follow the sets below.
|
25
|
+
|
26
|
+
- Change the URL of your browser to the respository, pull request or issue you want to open on gitpod e.g. for the [profiler project](https://github.com/firefox-devtools/profiler), URL of the upstream repository is `https://github.com/firefox-devtools/profiler`. You can also use the forked repository if you wish to start contributing to the project.
|
27
|
+
- Prefix the URL in the address bar of your browser with `gitpod.io/#` e.g. `https://github.com/firefox-devtools/profiler` becomes `https://gitpod.io/#https://github.com/firefox-devtools/profiler`.
|
28
|
+
- Gitpod will then launch a workspace for you and clone the repository, branch, commit or pull request depending on the URL in the first step.
|
29
|
+
|
30
|
+
## Using the gitpod browser extension (optional)
|
31
|
+
|
32
|
+
You can also install the [gitpod browser extension](https://addons.mozilla.org/en-GB/firefox/addon/gitpod/) if you wish instead of prefixing the URL of your browser with `gitpod.io/#` as described in the first step of **Advanced usage** section.
|
33
|
+
|
34
|
+
The browser extension, if you choose to install, will add a button on each repository on Github. Clicking the button will trigger creation of an automatic gitpod setup.
|
35
|
+
|
36
|
+
|
37
|
+
|
38
|
+
|
39
|
+
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# Perf Profiling on Android
|
2
|
+
|
3
|
+
Android has an application [`simpleperf`](https://android.googlesource.com/platform/system/extras/+/master/simpleperf/doc/README.md) which can profile any Android process. Simpleperf is mostly a drop-in replacement for the Linux `perf` tool.
|
4
|
+
|
5
|
+
Firefox Profiler can visualise these `simpleperf` profiles, augmenting the viewers that ship with `simpleperf` (e.g. [`report_html.py`](https://android.googlesource.com/platform/system/extras/+/master/simpleperf/doc/scripts_reference.md#report_html_py)).
|
6
|
+
|
7
|
+
For specifically profiling Firefox for Android, see [Remote Profiling Firefox for Android](guide-remote-profiling.md).
|
8
|
+
|
9
|
+
## Install simpleperf
|
10
|
+
|
11
|
+
Install the latest version of `simpleperf`, which can output profiles for Firefox Profiler:
|
12
|
+
|
13
|
+
```bash
|
14
|
+
git clone https://android.googlesource.com/platform/system/extras
|
15
|
+
cd extras/simpleperf
|
16
|
+
```
|
17
|
+
|
18
|
+
## Usage instructions
|
19
|
+
|
20
|
+
### Step 1: Capture the profile
|
21
|
+
|
22
|
+
Record a profile following [the simpleperf instructions](https://android.googlesource.com/platform/system/extras/+/master/simpleperf/doc/scripts_reference.md#app_profiler_py), e.g. to profile the startup of `MyActivity` within app `com.example.myapplication`, run:
|
23
|
+
|
24
|
+
```bash
|
25
|
+
./app_profiler.py -p com.example.myapplication -a .MyActivity
|
26
|
+
```
|
27
|
+
|
28
|
+
This records the profile into a `perf.data` file, and pulls it to your host.
|
29
|
+
|
30
|
+
### Step 2: Convert the profile
|
31
|
+
|
32
|
+
Then convert to a Gecko Profile (Firefox Profiler) format, using [`gecko_profile_generator.py`](https://android.googlesource.com/platform/system/extras/+/master/simpleperf/doc/scripts_reference.md#gecko_profile_generator_py):
|
33
|
+
|
34
|
+
```bash
|
35
|
+
./gecko_profile_generator.py | gzip > profile.json.gz
|
36
|
+
```
|
37
|
+
|
38
|
+
`gecko_profile_generator.py` takes the `perf.data` file that was written before as its implicit input.
|
39
|
+
|
40
|
+
### Step 3: View the profile in profiler.firefox.com
|
41
|
+
|
42
|
+
Load `profile.json.gz` into [profiler.firefox.com](https://profiler.firefox.com), using drag-and-drop or "Load a profile from file".
|
43
|
+
|
44
|
+
## See also
|
45
|
+
|
46
|
+
The tips in [Perf Profiling for Linux](guide-perf-profiling.md).
|
@@ -0,0 +1,87 @@
|
|
1
|
+
# Filtering call trees
|
2
|
+
|
3
|
+
Call trees can grow to be quite large, especially when profiling a browser engine. Typically, only portions of the tree are actually useful for any given analysis. The Firefox Profiler provides a variety of tools for filtering and transforming a tree in order to only show the relevant parts. It's important when filtering to know the difference between filtering out samples and transforming stacks. When removing samples, the tree will essentially be the same shape, but may be missing certain branches that were only present in certain samples. When transforming the tree, the shape of the sample's stacks will be modified. Samples will only be dropped if their stacks are completely removed during the transformation operation.
|
4
|
+
|
5
|
+
The following are the different types of filtering operations that are supported.
|
6
|
+
|
7
|
+
| Filter type | Description |
|
8
|
+
| ----------- | ----------- |
|
9
|
+
| Search filter | Drop samples that do not match a text string. |
|
10
|
+
| Implementation filter | Restrict stacks to an implementation—native (C++) stacks, or to JavaScript stacks. |
|
11
|
+
| Invert call stack | Flip the sample's stacks upside down and build a new call tree. |
|
12
|
+
| Transforms | Modify the shape of the call tree according to some operation. Typically, this only modifies the stacks. |
|
13
|
+
|
14
|
+
## Search filter
|
15
|
+
|
16
|
+
![A screenshot of the search box](./images/search-2022-06-16.png)
|
17
|
+
|
18
|
+
Searching will exclude samples that do not match a search string. The search filter looks at every function in the sample's stack. If the function's name, resource, or URL match, then the sample will be retained; otherwise, it will be filtered out. Multiple search terms can be added, as long as they are separated by commas.
|
19
|
+
|
20
|
+
![The image demonstrates the search filter. On the left is a call tree that has all stacks, and on the right is the filtered call tree that does not have any stacks that do not have the function C.](./images/filter-search.svg)
|
21
|
+
|
22
|
+
The above diagram is reproduced in the profile below:
|
23
|
+
|
24
|
+
* Before searching: [https://perfht.ml/2I3SMsR](https://perfht.ml/2I3SMsR)
|
25
|
+
* After searching: [https://perfht.ml/2rbcj0N](https://perfht.ml/2rbcj0N)
|
26
|
+
|
27
|
+
The following are some ideas on how to use search terms:
|
28
|
+
|
29
|
+
* `js::` - Filter for a C++ namespace.
|
30
|
+
* `www.example.com` - Filter for a domain name.
|
31
|
+
* `www.example.com/assets/scripts.js` - Filter for a single script.
|
32
|
+
|
33
|
+
## Implementation filter
|
34
|
+
|
35
|
+
![A screenshot of the implementation filter dropdown.](./images/implementation-2022-06-16.png)
|
36
|
+
|
37
|
+
The implementation filter is useful for narrowing down the call tree to a subset of stack types. For instance, it can be useful to only show native stacks (C++ and Rust) or to only show JavaScript stacks.
|
38
|
+
|
39
|
+
The following graphic demonstrates how it can be useful to filter to only JavaScript stacks.
|
40
|
+
|
41
|
+
![This graphic shows going from a combination of mixed native stacks and JavaScript stacks to only JavaScript stacks. The shape JavaScript stacks are interleaved on the mixed graph, but form a single non-branching tree in the JavaScript only version.](./images/implementation-filter.svg)
|
42
|
+
|
43
|
+
Before the implementation filter, the call tree contains both C++ JavaScript internals, as well as the JavaScript stacks. This interleaving could be useful when diagnosing how the JS engine is optimizing code, but for normal JS performance, profiling this could be confusing to find hot JS functions. When the native stacks are removed, the call tree that is generated is much more sensible for representing the execution of JavaScript code.
|
44
|
+
|
45
|
+
The implementation filter will modify the shape of stacks and generate a completely new call tree. If any of the filtered stacks in a sample are empty (for instance filtering on JavaScript when there are only C++ stacks), then those samples with empty stacks will be dropped from the analysis.
|
46
|
+
|
47
|
+
## Invert call stack
|
48
|
+
|
49
|
+
![A screenshot of the "Invert call stacks" checkbox.](./images/invert-2022-06-16.png)
|
50
|
+
|
51
|
+
Inverting the call stacks of samples will produce an entirely new call tree. All of the self time will be at the roots of the call tree. The implications to the shape of the call tree may be surprising, but consider the following graphics.
|
52
|
+
|
53
|
+
![An image showing samples on the left and the call tree on the right. This is before the invert operation.](./images/invert-before.svg)
|
54
|
+
|
55
|
+
In this profile, for the sake of brevity, there are only 3 samples that were collected 1ms apart. In most uninverted call trees, there is only one root node. In this case, `A` calls `B` and it's not until the third stack frames where the calls diverge to function `X` and function `C`. The call tree on the right is what is produced from these samples. Now consider inverting all of the stacks in the samples.
|
56
|
+
|
57
|
+
![An image showing samples on the left and the call tree on the right. This is after the invert operation.](./images/invert-after.svg)
|
58
|
+
|
59
|
+
Previously, the stacks `X -> Y -> Z` were each at different levels. However, in the inverted view, the stacks are now at the same level. When the call tree is created from these samples, there are now two different roots, starting from the function `Z` and the function `E`. The inversion made the `Z -> Y -> X` portions of the stacks fall into the same level.
|
60
|
+
|
61
|
+
Inversion is most useful in surfacing the functions where time is actually being spent. The trees are typically much larger and noisier than uninverted call trees.
|
62
|
+
|
63
|
+
## Transforms
|
64
|
+
|
65
|
+
Call tree transforms provide a finer grain control over how to modify the call tree. They modify the stack in different operations. They can operate at individual call nodes on the tree, or across the entire tree for a given function. Different programs use different terms to describe these operations, but the Firefox Profiler has defined certain operations.
|
66
|
+
|
67
|
+
![A screenshot of the transforms in the contextmenu.](./images/transforms-2022-06-16.png)
|
68
|
+
|
69
|
+
### Merge
|
70
|
+
|
71
|
+
Merging takes a call node and removes it from the call tree. Any self time for that node is then charged to its parent node. This can be done for a single call node, or for all functions in the tree. This type of operation can be useful for modifying the shape of the tree and removing unhelpful functions from the call tree.
|
72
|
+
|
73
|
+
### Focus
|
74
|
+
|
75
|
+
Focusing on a function or call node removes all of the ancestor call nodes—the children call nodes remain. If a stack does not contain that function or node, then it is removed. This effectively focuses on a subtree or a set of subtrees on the call tree.
|
76
|
+
|
77
|
+
### Focus on Category
|
78
|
+
|
79
|
+
Focusing on the nodes that belong to the same category as the selected node, thereby merging all nodes that belong to another category.
|
80
|
+
|
81
|
+
### Collapse
|
82
|
+
|
83
|
+
Collapsing functions is an operation that takes multiple call nodes and combines them all together into a new single call node. This can be done for an entire subtree, in order to reduce the amount of nodes in the tree. This can also be done for contiguous call nodes. For example, it can be useful to collapse functions that are all part of some library or call nodes that are recursing.
|
84
|
+
|
85
|
+
### Drop
|
86
|
+
|
87
|
+
Dropping is used to mean removing samples, but not changing any properties of the stacks. This could be useful for dropping functions that are prevalent like idle functions, but that gets in the way of analysis.
|
@@ -0,0 +1,115 @@
|
|
1
|
+
# Getting Started
|
2
|
+
|
3
|
+
This page is an overview of the general process of capturing a profile.
|
4
|
+
|
5
|
+
## Access the Firefox Profiler controls
|
6
|
+
|
7
|
+
The Firefox Profiler can be used with 2 entry points: either from the popup, or
|
8
|
+
from the devtools panel.
|
9
|
+
|
10
|
+
?> We recommend using the popup so that the overhead
|
11
|
+
caused by the other devtools is avoided.
|
12
|
+
|
13
|
+
### Enable the popup
|
14
|
+
|
15
|
+
The simplest way to enable the popup is going to https://profiler.firefox.com
|
16
|
+
and clicking the big button `Enable Firefox Profiler Menu Button` in the page.
|
17
|
+
|
18
|
+
![A screenshot of the profiler website homepage highlighting the button](images/getting-started-enable-popup.png)
|
19
|
+
|
20
|
+
You can also drag and drop the icon from the toolbar customization
|
21
|
+
interface.
|
22
|
+
|
23
|
+
### Open the popup
|
24
|
+
|
25
|
+
You open the popup by clicking the small arrow on the side of the profiler icon.
|
26
|
+
|
27
|
+
![A screenshot of the profiler popup](images/getting-started-popup.png)
|
28
|
+
|
29
|
+
There you can change the preset as well as access the advanced settings.
|
30
|
+
|
31
|
+
?> We
|
32
|
+
suggest using the preset `Firefox` (also called `Nightly` if running in the
|
33
|
+
nightly version of Firefox) if you want to profile the full browser (for
|
34
|
+
example to [report a performance problem in Firefox](https://firefox-source-docs.mozilla.org/performance/reporting_a_performance_problem.html)),
|
35
|
+
and `Web Developer` if you want to profile a web site.
|
36
|
+
|
37
|
+
### Using the Devtools panel
|
38
|
+
|
39
|
+
The same settings are available in the devtools panel.
|
40
|
+
|
41
|
+
![A screenshot of the Devtools performance panel](images/getting-started-devtools-panel.png)
|
42
|
+
|
43
|
+
!> As explained above, when opening the Devtools toolbox there's an
|
44
|
+
overhead, due to additional open panels. We try to maintain a minimal overhead,
|
45
|
+
but you need to keep this into account when looking at profiles that were
|
46
|
+
captured from this panel.
|
47
|
+
|
48
|
+
## Capture a profile
|
49
|
+
|
50
|
+
### Using the popup or the devtools panel
|
51
|
+
|
52
|
+
[A video showing how to use the profiler popup](images/getting-started-use-popup.webm ':include :type=video controls')
|
53
|
+
|
54
|
+
You can use the popup from the icon, or similarly the devtools panel, by
|
55
|
+
clicking on `Start Recording`, then `Capture`. Then the profiler user interface
|
56
|
+
will open to show the captured data.
|
57
|
+
|
58
|
+
Note that the profiler user interface is an external web page, however it's
|
59
|
+
cached locally the first time you access it. This means you'll need a network
|
60
|
+
connection to download it the first time you use it. If you have a network
|
61
|
+
connection in later uses and a new version is available, the UI will offer to
|
62
|
+
switch to the new version.
|
63
|
+
|
64
|
+
It's also important to know that the data stays local to your computer until you
|
65
|
+
upload it (see below).
|
66
|
+
|
67
|
+
### Using the profiler button
|
68
|
+
|
69
|
+
It's possible to click on the button to start the profiler with current
|
70
|
+
settings. Then click it again to capture the profile and the open the profiler
|
71
|
+
UI.
|
72
|
+
|
73
|
+
[A video showing how to use the profiler icon](images/getting-started-use-icon.webm ':include :type=video controls')
|
74
|
+
|
75
|
+
### Using keyboard shortcuts
|
76
|
+
|
77
|
+
The following keyboard shortcuts are available:
|
78
|
+
|
79
|
+
* `Ctrl + Shift + 1`: start the profiler, or stop and discard the data if it's already running.
|
80
|
+
* `Ctrl + Shift + 2`: capture the profile from the currently running session. It
|
81
|
+
has no effect if the profiler isn't running.
|
82
|
+
|
83
|
+
## Share a profile
|
84
|
+
|
85
|
+
![A screenshot highlighting the toolbar's upload profile button.](images/getting-started-upload.png)
|
86
|
+
|
87
|
+
One of the most powerful and useful features of the Firefox Profiler is the ability to upload and share profiles. The first step is to hit the *Upload Local Profile* button. You'll be able to exclude some information before uploading. Then the profile will be uploaded to an online storage. This profile can then be shared in online chat, emails, and bug reports. Note that anybody that has the link will be able to access the uploaded data, as it's not protected otherwise.
|
88
|
+
|
89
|
+
The current view and all of the filters applied to the profile will be encoded into the URL. After initially sharing the profile, a *Permalink* button will be added, that can then be used to provide a handy shortened URL to the current view.
|
90
|
+
|
91
|
+
[A video showing how to upload a profile and how to get the permalink](images/getting-started-upload-permalink.webm ':include :type=video controls')
|
92
|
+
|
93
|
+
?> Profiles can also be saved to file, although the current view into the UI will not be saved. The file can be reloaded through the [profiler.firefox.com](https://profiler.firefox.com) interface by either drag and drop, or the file upload interface.
|
94
|
+
|
95
|
+
## Delete an uploaded profile
|
96
|
+
|
97
|
+
After uploading a profile, you can delete it from the `Profile info` panel.
|
98
|
+
|
99
|
+
![A screenshot showing the delete button in the profile info panel](images/getting-started-delete-profile.png)
|
100
|
+
|
101
|
+
You can also go to the [Uploaded Recordings page](/uploaded-recordings/ ':ignore') to list
|
102
|
+
all profiles you uploaded and delete them. Note that this list is only stored
|
103
|
+
locally in your Firefox, and for this reason you can delete only profiles that
|
104
|
+
you uploaded from the same browser instance.
|
105
|
+
|
106
|
+
![A screenshot showing the list of uploaded profiles](images/getting-started-list-uploaded-profiles.png)
|
107
|
+
|
108
|
+
## Name a profile
|
109
|
+
|
110
|
+
![A screenshot highlighting the location for the name of a profile](images/getting-started-naming-profiles.png)
|
111
|
+
|
112
|
+
It's possible to name a profile so that it's conveniently findable later by
|
113
|
+
searching in the address bar. The name is part of the URL you'll share to others,
|
114
|
+
but otherwise isn't stored in the profile data.
|
115
|
+
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# Profiling with Linux perf
|
2
|
+
|
3
|
+
Linux has a native profiler called 'perf' that can profile any application. This profiler has a built-in profile viewer in the form of the `perf report` command, but you may not like its UI.
|
4
|
+
|
5
|
+
[The Firefox Profiler](https://profiler.firefox.com/) provides an alternative UI for these profiles; it knows how to display profiles from perf.
|
6
|
+
|
7
|
+
(Importing other profile sources is being investigated, such as in [issue #1138](https://github.com/firefox-devtools/profiler/issues/1138), and [issue #1553](https://github.com/firefox-devtools/profiler/issues/1553).)
|
8
|
+
|
9
|
+
There are three major differences between the Gecko profiler and perf:
|
10
|
+
|
11
|
+
1. The Gecko profiler can only profile Gecko. Perf can profile any process on the system.
|
12
|
+
2. The Gecko profiler samples at a fixed rate based on wall-clock time. Perf samples based on elapsed CPU time per thread.
|
13
|
+
3. The Gecko profiler only samples a small set of threads by default. Perf samples all threads of the given process or process tree.
|
14
|
+
|
15
|
+
As a consequence of point 2, perf has far lower overhead than the Gecko Profiler when profiling many threads: perf only takes a sample whenever a thread is running, whereas the Gecko profiler will keep sampling all profiled threads at a fixed rate even when those threads are idle.
|
16
|
+
|
17
|
+
## Usage instructions
|
18
|
+
|
19
|
+
(This assumes you've installed perf.)
|
20
|
+
|
21
|
+
There are three steps to obtaining a perf profile and loading it in the Firefox Profiler:
|
22
|
+
|
23
|
+
1. Capture a profile with perf.
|
24
|
+
2. Convert it into a text form.
|
25
|
+
3. Load the text file in [profiler.firefox.com](https://profiler.firefox.com).
|
26
|
+
|
27
|
+
### Step 1: Capture the profile
|
28
|
+
|
29
|
+
You can attach perf to an existing (running) process, or you can launch a new process from it and profile it from the start, including the entire process tree launched from it.
|
30
|
+
|
31
|
+
To attach to an existing process with PID `<pid>`, use:
|
32
|
+
|
33
|
+
```bash
|
34
|
+
perf record -g -F 999 -p <pid>
|
35
|
+
# Stop with Ctrl+C once you've collected enough
|
36
|
+
```
|
37
|
+
|
38
|
+
To launch a new process under the profiler, use
|
39
|
+
|
40
|
+
```bash
|
41
|
+
perf record -g -F 999 program options
|
42
|
+
# Stop with Ctrl+C once you've collected enough
|
43
|
+
```
|
44
|
+
|
45
|
+
For Firefox, this would be:
|
46
|
+
|
47
|
+
```bash
|
48
|
+
perf record -g -F 999 firefox -P profile -no-remote
|
49
|
+
```
|
50
|
+
|
51
|
+
The `perf record` command writes the profile into a file called `perf.data` in the current directory.
|
52
|
+
|
53
|
+
### Step 2: Convert the profile
|
54
|
+
|
55
|
+
After exiting perf, convert the perf data into something the Firefox Profiler can read:
|
56
|
+
|
57
|
+
```bash
|
58
|
+
perf script -F +pid > /tmp/test.perf
|
59
|
+
```
|
60
|
+
|
61
|
+
The `perf script` command takes the `perf.data` file that was written by the `perf record` command as its implicit input.
|
62
|
+
|
63
|
+
### Step 3: View the profile in profiler.firefox.com
|
64
|
+
|
65
|
+
You can now load the .perf file into [profiler.firefox.com](https://profiler.firefox.com): tell the Firefox Profiler to open the file and it should be auto-identified and loaded.
|
66
|
+
Note that there will be no markers and no categories. Many stack frames will say `[unknown]`. There will be no JavaScript stacks, unless you do extra work as described below. Symbols might be mangled.
|
67
|
+
|
68
|
+
## Analyzing perf traces and tips
|
69
|
+
|
70
|
+
Remember that 'perf' only records a sample if the thread is executing; samples are omitted if the thread is sleeping. This means in many cases there will be gaps between samples, often large ones. You probably want to switch from "Categories" to "Stack height" mode in the top left corner in order to see when samples were taken across the different threads.
|
71
|
+
|
72
|
+
Perf sometimes has trouble walking the stack, and you'll get mis-rooted subtrees at the top level.
|
73
|
+
|
74
|
+
Perf can include kernel callstacks in the profile. They might show up as `[unknown]` frames from the `[kernel.kallsyms]` library. Setting `/proc/sys/kernel/perf_event_paranoid` to 1 or less can potentially help with this.
|
75
|
+
|
76
|
+
If you need JavaScript stacks, you can build Firefox with `--enable-perf` and then run it with the env variable `IONPERF=func`. This will allow some of the `[unknown]` frames to be resolved to JS source files/functions. Doing so does have some impact on the recorded profile, but it's generally small.
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# Profiler Fundamentals
|
2
|
+
|
3
|
+
When profiling code, there are two primary sources of information—stack: samples and markers.
|
4
|
+
|
5
|
+
## Samples
|
6
|
+
|
7
|
+
For samples, the profiler stops the execution of the profiled code at a fixed rate, for example, every 1ms and records relevant information like the current stack. These samples are aggregated together and provide a statistical look into the execution of the program. There is no guarantee that all of the code that is running will be sampled, but with enough samples, it provides a good look into where time was spent while running the targeted code.
|
8
|
+
|
9
|
+
### Statistical significance and the overhead of samples
|
10
|
+
|
11
|
+
There are two ways to get more samples to provide more statistical significance. The first way is to increase the sampling rate. The sampling rate can be changed by tweaking the sampling interval in about:profiling.
|
12
|
+
|
13
|
+
![A picture of the UI in about:profiling to adjust the sampling interval.](images/interval-2020-05.png)
|
14
|
+
|
15
|
+
For example, the sampling rate could be increased by changing the interval from 1ms to 0.1ms to collect 10 times more samples. This makes it possible to run the profiled program fewer times, but comes with a trade-off. When the profiler is collecting more samples, the profiler needs to do more work to collect these samples and thus, there is more overhead from the profiler. This can skew the results by measuring more of the overhead of profiling, compared to the actual program that is being run.
|
16
|
+
|
17
|
+
The other way to increase the number of samples is to run the code more often and not increase the sampling rate. For instance, to profile a mouse click event, one click event would not be sampled much with a frequency of 1ms. However, performing the click event multiple times over the course of a minute would increase the amount of samples collected, without introducing additional overhead from the profiler.
|
18
|
+
|
19
|
+
## Markers
|
20
|
+
|
21
|
+
Samples provide a view into the profiled program that is based on probability. Over time, with enough samples, the analysis will most likely contain samples of the code that was run. However, it can miss important events that happen quickly.
|
22
|
+
|
23
|
+
Markers provide a view into the executing code that does not miss anything. Markers are small pieces of data that are collected every time a specific event happens. For instance, when clicking the mouse, the C++ implementation could call a function that collects the current mouse coordinates and timestamp of the event. This information would then be stored in the profiler's buffer. This mouse click could happen very quickly and most likely it would be missed by the profiler if not for the marker.
|
24
|
+
|
25
|
+
Samples are a general-purpose solution to understand what is going on in the code, while markers provide a specific opinionated view. A very fast mouse event will have a high probability of being missed on a low sampling rate, but will always be collected as a marker. The problem with markers is that they must be hand-instrumented in the code and kept up to date. They are a great way for engineers with domain-specific information to surface more information about how a program is executing. The marker information can be cross-referenced with the samples to provide a better understanding of what code is doing.
|
26
|
+
|
27
|
+
Markers can be used for stack-like purposes as well. For instance, when working with React or any front-end component system, the JavaScript stacks will all be framework internals. The internals are resolving work requested by the components, but they do not directly map to the code that the component author wrote. To get around this, components could emit markers with start and end timestamps for when they are updated. These markers can then be turned into a chart that shows how components are rendering according to a hierarchy and how much time is being spent updating them. This labeled information can then be cross referenced with the statistically collected samples.
|
28
|
+
|
29
|
+
### Overhead and trade-offs with markers
|
30
|
+
|
31
|
+
While markers can provide very detailed information about a given system, they do come with some trade-offs. Unlike samples which are a generalized solution, each type of marker must be written and maintained as lines of code in the source. This requires a domain-expert's time and bandwidth to create. In addition, if this information is not correctly maintained, it could potentially be out of date and provide faulty information.
|
32
|
+
|
33
|
+
The process of collecting samples has a convenient knob to tune the overhead—the sample rate. Markers will be collected every time an event happens. This is really nice for interesting parts of the profiled program, but can start to fall apart if overused. For instance, if every single part of the JavaScript engine was instrumented to collect a marker for how it executed, this would quickly turn into gigabytes of memory that would be slow to process, difficult to store and probably skew the results with a large amount of overhead.
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# Profiling Firefox for Android directly on device
|
2
|
+
|
3
|
+
The Firefox Profiler can be used without the remote debugging option. It offers a little less flexibility (can't edit the options and the profile is
|
4
|
+
automatically uploaded). However, it does allow you to capture a profile without the need of a PC.
|
5
|
+
|
6
|
+
## Setup
|
7
|
+
|
8
|
+
### Pick a build to profile
|
9
|
+
We recommend profiling a Firefox build from any release channel (i.e. not debug), whether downloaded from Google Play, Taskcluster, or built locally.
|
10
|
+
|
11
|
+
### Enable secret settings on the mobile device
|
12
|
+
|
13
|
+
To enable secret settings, follow these steps:
|
14
|
+
|
15
|
+
- Click on the [three dot icon next to the URL bar](./images/about-url.png)
|
16
|
+
- Select the ["Settings" option](./images/settings-menu.png).
|
17
|
+
- Scroll to the bottom of the settings page and select the "About Firefox"
|
18
|
+
- Click the "Firefox" logo 5 times. [A toast should appear at the bottom of your screen with the number of click left before unlocking the secret menu](./images/secret-menu-toast.png).
|
19
|
+
- Go back to the "Settings" screen and scroll to the bottom where you should see the ["Start Profiler" option](./images/start-profiler.png).
|
20
|
+
|
21
|
+
## Usage instructions
|
22
|
+
|
23
|
+
### To start the profiler
|
24
|
+
|
25
|
+
- Click on "Start Profiler" and you should see a dialogue appear.
|
26
|
+
- Choose one of the four options that matches the closest to what you're trying to profile.
|
27
|
+
- Click "Start Profiler" and a toast should appear with the "Profiler started" message.
|
28
|
+
|
29
|
+
### To stop the profiler
|
30
|
+
|
31
|
+
- Go back to the Settings screen
|
32
|
+
- Scroll to the bottom and you should see a "Stop profiler" option has replaced the "Start Profiler" one.
|
33
|
+
- After you click it, you should see a dialogue with a warning regarding the information contained in the profile.
|
34
|
+
- Once stopped, the URL for the profile that finished recording will be copied to your clipboard which you can then use to share.
|
@@ -0,0 +1,7 @@
|
|
1
|
+
# Profiling Firefox for Android
|
2
|
+
|
3
|
+
Two options are possible:
|
4
|
+
|
5
|
+
* [Remote Profiling Firefox for Android](./guide-remote-profiling.md) provides the most options but can be cumbersome to set up;
|
6
|
+
* [Profiling Firefox for Android directly on the device](./guide-profiling-android-directly-on-device.md) has fewer options but should be easier to set up.
|
7
|
+
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# Remote Profiling Firefox for Android
|
2
|
+
|
3
|
+
You can use the Firefox Profiler to investigate performance issues on Android, not only Windows, macOS and Linux.
|
4
|
+
|
5
|
+
In order to do so, you need both your phone with the mobile Gecko-based browser, and a machine running Firefox Desktop. You also need a USB connection between the two devices. Then you can use [about:debugging](https://developer.mozilla.org/en-US/docs/Tools/about:debugging) in Firefox Desktop to connect to the phone and control profiling from there. The result will be shown in Firefox Desktop.
|
6
|
+
|
7
|
+
[In this 1 minute video demonstration](https://www.youtube.com/watch?v=TxAlQBv6-yg) you can see the few steps needed to capture a profile from Fenix. For additional details and troubleshooting info, see below.
|
8
|
+
|
9
|
+
## Setup
|
10
|
+
|
11
|
+
### Pick a build to profile
|
12
|
+
We recommend profiling a Firefox build from any release channel (i.e. not debug), whether downloaded from Google Play, Taskcluster, or built locally. Alternatively, you may wish to profile GeckoView-example. For more details, see the [Which mobile browser? section below](#which-mobile-browser).
|
13
|
+
|
14
|
+
### Enable remote debugging on the mobile device
|
15
|
+
|
16
|
+
Your device needs to be connected to your computer before recording. You also need to have your Gecko-based Android app (such as Firefox Preview) running and set up for remote debugging via USB. This usually requires **two** settings:
|
17
|
+
|
18
|
+
- Android itself needs to be configured to allow remote debugging over USB. This can be done in the system settings after entering "developer mode", which can be done by tapping on the Android build number repeatedly. See [the Android documentation](https://developer.android.com/studio/debug/dev-options.html) for details.
|
19
|
+
- The app needs to be configured to allow remote debugging. There's usually a checkbox in the app's settings menu for that.
|
20
|
+
|
21
|
+
### Prepare `about:debugging`
|
22
|
+
|
23
|
+
To profile a Gecko Android build, you have to connect it to a Desktop Firefox browser. Please use [Firefox Nightly](https://www.mozilla.org/en-US/firefox/channel/desktop/#nightly) for this.
|
24
|
+
|
25
|
+
* Open the `about:debugging` page in Desktop Firefox by typing `about:debugging` in the URL bar, or via Tools > Web Developer > Remote Debugging.
|
26
|
+
* If necessary, click "Enable USB Devices".
|
27
|
+
|
28
|
+
## Recording
|
29
|
+
|
30
|
+
On `about:debugging`, find your device/browser in the sidebar on the left and connect to it. If your device is not listed, check the following things:
|
31
|
+
|
32
|
+
- Is USB debugging enabled in the Android system preferences?
|
33
|
+
- Is the browser you want to profile running? Try navigating to a page in order to make sure that Gecko has been initialized.
|
34
|
+
- Is remote debugging enabled in the browser on the phone? If you've recently pushed a new version of this app to your phone, the settings from the previous version may have been lost, so you may need to enable the pref again.
|
35
|
+
- Is your phone's screen unlocked?
|
36
|
+
- Double-check your cable connections.
|
37
|
+
- If you have `adb` on your Desktop machine, check if `adb devices` sees the phone. If not, try to fix that first.
|
38
|
+
|
39
|
+
Once you have connected to the phone browser successfully, read on.
|
40
|
+
|
41
|
+
Click the sidebar item for your phone / browser. Then, in the main section of the page, click the *Profile Performance* button.
|
42
|
+
|
43
|
+
Make any necessary adjustments in the presented options, like threads to sample or profiler features to enable, and then click *Start recording*. Perform the interactions you intend to profile on the Android device and then click *Capture Recording* in the Performance panel. A new tab will open in [https://profiler.firefox.com/](https://profiler.firefox.com/) with the collected profile ready for inspection.
|
44
|
+
|
45
|
+
![A screenshot of about:debugging after connecting](./images/about-debugging-remote.png)
|
46
|
+
![A screenshot of about:debugging after clicking Profile Performance](./images/about-debugging-remote-profiling-panel.png)
|
47
|
+
|
48
|
+
## Symbols and symbol sources
|
49
|
+
|
50
|
+
If you've been profiling a browser from the Google Play Store, your profile should contain fully symbolicated C++ call stacks at least for libxul.so. If it doesn't, check the following:
|
51
|
+
|
52
|
+
- Are you profiling a "shippable" GeckoView build? A common mistake is to profile a regular "opt" build from treeherder, i.e. one that was not compiled with the "shippable" configuration. Unfortunately, those regular treeherder builds do not upload symbol information to the Mozilla symbol server. Please use a different build in that case.
|
53
|
+
- Are you profiling a build from the tryserver or a local build? Read on below for how to obtain symbol information in those cases.
|
54
|
+
|
55
|
+
## Which mobile browser?
|
56
|
+
|
57
|
+
(The following is true as of August 2021.)
|
58
|
+
|
59
|
+
You probably want to profile [Firefox Nightly](https://play.google.com/store/apps/details?id=org.mozilla.fenix) from the Google Play Store. Read on for more details, or skip to the next section if you already know exactly which browser you want to profile.
|
60
|
+
|
61
|
+
Mozilla's current development efforts on mobile are focused on GeckoView and Firefox for Android (["Fenix"](https://github.com/mozilla-mobile/fenix)). You can [install Firefox Nightly from the Google Play Store](https://play.google.com/store/apps/details?id=org.mozilla.fenix), or you can download the APK ([32 bit](https://firefox-ci-tc.services.mozilla.com/api/index/v1/task/mobile.v3.firefox-android.apks.fenix-nightly.latest.armeabi-v7a/artifacts/public/build/fenix/armeabi-v7a/target.apk), [64 bit](https://firefox-ci-tc.services.mozilla.com/api/index/v1/task/mobile.v3.firefox-android.apks.fenix-nightly.latest.arm64-v8a/artifacts/public/build/fenix/arm64-v8a/target.apk)). Firefox Nightly is the preferred profiling target. It uses a [recent](https://github.com/mozilla-mobile/android-components/blob/master/buildSrc/src/main/java/Gecko.kt#L9) version of Gecko and updates frequently and automatically.
|
62
|
+
|
63
|
+
The other reasonable profiling target is something called ["GeckoView-example"](https://searchfox.org/mozilla-central/source/mobile/android/geckoview_example). This is a small Android app that isn't much more than a demo of GeckoView and doesn't have much UI. You can download the most recent GeckoView-example.apk ([32 bit](https://firefox-ci-tc.services.mozilla.com/api/index/v1/task/gecko.v2.mozilla-central.shippable.latest.mobile.android-arm-opt/artifacts/public/build/geckoview_example.apk), [64 bit](https://firefox-ci-tc.services.mozilla.com/api/index/v1/task/gecko.v2.mozilla-central.shippable.latest.mobile.android-aarch64-opt/artifacts/public/build/geckoview_example.apk)) from TaskCluster, or you can compile Gecko yourself and [push Geckoview-example to the phone using `mach run`](https://firefox-source-docs.mozilla.org/mobile/android/geckoview/contributor/for-gecko-engineers.html#geckoview-example-app) or [using Android Studio](https://firefox-source-docs.mozilla.org/mobile/android/geckoview/contributor/geckoview-quick-start.html#build-using-android-studio). In fact, if you're working on Gecko, this is the most low-friction workflow if you want to quickly verify the performance impact of your changes on Android.
|
64
|
+
|
65
|
+
In general, profiling Fenix is preferable over profiling GeckoView-example because you'll be able to see impact from Fenix-specific performance issues. If you're compiling and modifying Gecko locally, you can create a version of Fenix that uses your custom Gecko [by making a small tweak to a `local.properties` file](https://firefox-source-docs.mozilla.org/mobile/android/geckoview/contributor/geckoview-quick-start.html#dependency-substiting-your-local-geckoview-into-a-mozilla-project) in your local clone of [the Fenix repository](https://github.com/mozilla-mobile/fenix).
|
66
|
+
|
67
|
+
You can also profile local builds or Try builds. This requires some extra steps which are described further down in this document.
|
68
|
+
|
69
|
+
## Startup profiling
|
70
|
+
|
71
|
+
To profile the startup of GeckoView or Firefox for Android, please look at [the
|
72
|
+
additional guide on the dedicated page](./guide-startup-shutdown#firefox-for-android).
|
73
|
+
|
74
|
+
### Try builds
|
75
|
+
|
76
|
+
If you want to profile an Android build that the tryserver created for you, you have to kick off a "Sym" job (run time: about 3 minutes) on treeherder: Using treeherder's *Add new jobs* UI, schedule a "Sym" job for each platform whose "B" job you want symbols for. These jobs gather symbol information from the corresponding build job and upload it to the Mozilla symbol server so that the Firefox Profiler can use it.
|
77
|
+
|
78
|
+
### Local builds
|
79
|
+
|
80
|
+
If you've compiled an Android Gecko build locally, and want to profile it, you have to jump through one small extra hoop: Before profiling, in the *Profile Performance* panel in `about:debugging`, go to *Settings*, scroll down to the *Local build* section and add your Android build's objdir to the list. Then profile as usual, and you should be getting full symbol information.
|
81
|
+
|
82
|
+
## Tips
|
83
|
+
|
84
|
+
* Enable the "Screenshots" feature before profiling. Then you can see what's going on on the screen during your profiling run, which can be extremely helpful.
|
85
|
+
* Limit the duration of the profiling run. This will cut down on the profile size, which will reduce the time you have to wait when you click "Capture Profile". Smaller profiles are also less likely to crash the app due to memory limitations.
|
86
|
+
* Avoid clicking on any of the open tabs that are listed on the `about:debugging` page. Clicking on a tab will open a toolbox and add overhead by initializing content-side devtools code. For that reason, the profiling panel is separate from the toolbox.
|
87
|
+
* Choose a more relaxed profiling interval in order to reduce profiling overhead. 2ms to 5ms work well. This will give you less data but more accurate timings.
|
88
|
+
* To get maximally-realistic timings, consider using the "No Periodic Sampling" feature: This will cut down profiling overhead dramatically, but you won't have any stacks. If your workload is reproducible enough, you can take two profiles: one with stacks and one without. Then you can take your timings from the former and your information from the latter.
|
89
|
+
* Startup profiling reveals some overhead caused by devtools code that is only run when remote debugging is enabled. In order to see what startup does when remote debugging is turned off, you can deactivate remote debugging before you quit the app, and re-activate it after startup.
|
90
|
+
* If the recording doesn't start after clicking the start button, or if the button is inactive or in an otherwise confused state, it might be necessary to disconnect and reconnect to the phone to reset some state.
|
@@ -0,0 +1,4 @@
|
|
1
|
+
# Removing profiler
|
2
|
+
To remove the Firefox Profiler from the toolbar, right-click on the Profiler icon and choose "Remove from Toolbar" in the context menu.
|
3
|
+
|
4
|
+
The Firefox Profiler is built in Firefox. The icon is only a menu button (that you can remove). There is no need and no way to remove the whole Firefox Profiler.
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# Stack Samples and Call Trees
|
2
|
+
|
3
|
+
While samples can collect any type of arbitrary information, arguably the most useful is the call stack of the currently executing program. This document explores how to aggregate and analyze these stacks. It may be helpful to have first read the [profiler fundamentals](./guide-profiler-fundamentals) document for some of the theory behind how sampling works, and how the samples differ from markers.
|
4
|
+
|
5
|
+
## Stacks gathered over time
|
6
|
+
|
7
|
+
![This image shows contiguous stacks, and how they are sampled over time. It fades out as it goes left to right to indicate that samples are gathered for long periods of time. The stacks are labeled by 1 millisecond intervals. The stacks are labeled by functions that are single capital letters, ranged A to H.](./images/samples.svg)
|
8
|
+
|
9
|
+
These examples assume the profiler is configured to collect samples every 1 millisecond. As the targeted code runs, the profiler stops the program execution, and samples the stack. Often, the roots of the stacks will look very similar, but then the leaves will vary wildly as the code calls into different parts of the program. If a program is profiled for 3 seconds, at the rate of 1 millisecond per sample, then there would be 3000 samples. It is not practical to view samples individually, so these samples will be aggregated together to provide a more useful look into profile execution. This aggregated data structure is the call tree.
|
10
|
+
|
11
|
+
## A simplified call tree
|
12
|
+
|
13
|
+
![This image shows stacks going from left to right. They are at 1 millisecond intervals. Each stack is composed of the function, A, B, C, and doWork. There are 5 samples](./images/simple-stacks.svg)
|
14
|
+
|
15
|
+
<!--alex ignore simple-->
|
16
|
+
This example creates a fairly contrived and simple example. `A` calls `B`, which calls `C`, then calls `doWork`. `A`, `B`, `C` are very quick to run, and the profiler never directly samples them. However, `doWork` is sampled 5 times. An aggregation of this profile would smush everything into one graph.
|
17
|
+
|
18
|
+
![This graphic demonstrates a call tree. It is a chart of the stacks A, B, C, and doWork, each connected by an arrow going from the root A to the leaf doWork. The running time of all the samples is 5ms. The self time is 0ms, except for doWork, which has a self time of 5ms.](./images/simple-call-tree.svg)
|
19
|
+
|
20
|
+
This graph is a simplified call tree. Notice that there is no branching, as the samples that are aggregated all share the same stacks. The profiler only samples the function `doWork`, but the rest of the stack is in the report. This means that the running time for every node on the call tree is 5ms. (From here on out a node on a call tree will be referred to as a "call node"). However, since only the `doWork` function was observed, it is the only node to have self time of 5ms, as it was itself observed to be running. `A`, `B`, `C` all have a self time of 0ms.
|
21
|
+
|
22
|
+
## Self time in the call tree
|
23
|
+
|
24
|
+
Self time does not actually need to be found at the leaves of the call tree. In fact it can be located at any node in the tree. Self time is where the profiler observed a function running. Imagine in the previous example that the function `B` also required a bit of time to run.
|
25
|
+
|
26
|
+
![This image shows stacks going from left to right. They are at 1 millisecond intervals. The first and last stack are A, B, the middle three are A, B, C, and doWork.](./images/simple-stacks-self-time.svg)
|
27
|
+
|
28
|
+
This image shows that the profiler sampled `B` at the beginning and end of the profiling. This will not change the shape of the call tree, but it will change the self and running times reported.
|
29
|
+
|
30
|
+
![This graphic demonstrates the modified call tree. It is a chart of the stacks A, B, C, and doWork, each connected by an arrow going from the root A to the leaf doWork. A has a running time of 5ms, and a self time of 0ms. B has a running time of 5ms, and a self time of 2ms. C has a running time of 3ms, and a self time of 0ms. doWork has a running time of 3ms, and a self time of 3ms.](./images/simple-call-tree-self-time.svg)
|
31
|
+
|
32
|
+
The call node with the function `B` continues to have the running time of 5ms, but also has a self time of 2ms. Function `C` has a reduced running time of `3ms` and finally `doWork` was only observed `3ms` for both the running and self time.
|
33
|
+
|
34
|
+
In summary, self time is where work was actually happening when observed by the profiler.
|
35
|
+
|
36
|
+
## How to form a call tree
|
37
|
+
|
38
|
+
> Note: Feel free to follow along with a real call tree that reproduces this structure: [https://perfht.ml/2w45IdC](https://perfht.ml/2w45IdC)
|
39
|
+
|
40
|
+
<!--alex ignore simple-->
|
41
|
+
The simple call tree above did not take into account any branching stacks. It only concerned itself with running and self time. This section will dive into how the call tree handles stacks of different shapes.
|
42
|
+
|
43
|
+
![This image shows contiguous stacks, and how they are sampled over time. It fades out as it goes left to right to indicate that samples are gathered for long periods of time. The stacks are labeled by 1 millisecond intervals. The stacks are labeled by functions that are single capital letters, ranged A to H.](./images/samples.svg)
|
44
|
+
|
45
|
+
Consider the first 3 samples in this profile.
|
46
|
+
|
47
|
+
![On the left of this graph are three samples with different stacks. A, B, C, D, E. A, B, C, F, G. A, B, H, F, G. The bottom row with A is all grouped together. The second row with B is all grouped together. The third row has the two C functions grouped together, and the H distinct. All the rest of the function sare not grouped. The right graphic demonstrates the shape of the call tree.](./images/call-tree.svg)
|
48
|
+
|
49
|
+
These three samples share things in common. The root of each stack is the function `A`. These could be aggregated together into a single node. The same happens for node `B`. However the next level with the function `C` and `H` differ. At this point the call tree splits into two different nodes. There is a node for the function `C`, and the function `H`.
|
50
|
+
|
51
|
+
The call tree will continue merging functions that are at the same level, but only if they are part of the current branching pattern. For instance, consider function `F` and `G`. While both functions are at the same level of the stack, they are at different branching points. The middle `F -> G` stacks have `C` as their ancestor, and the right `F -> G` stacks have `H` as their ancestor, and thus are not grouped together.
|
52
|
+
|
53
|
+
A useful exercise at this point would be to consider [the running time](./images/call-tree-running-time.svg) and [self time](./images/call-tree-self-time.svg) of each node this call tree.
|
54
|
+
|
55
|
+
# Referring to call nodes in the call tree
|
56
|
+
|
57
|
+
The above example shows how functions F and G can appear multiple times in a call tree, thus it's ambiguous to refer to a call node by only its function name. Call nodes can be referred to by their call node paths, which are composed of a list of functions from root to leaf. The middle `G` call node in the tree would have the call node path `A, B, C, F, G`, while the one on the right would have the call node path `A, B, H, F, G`.
|