blob: 00945ac561041fd70fcfdaef9e9702a49c28d8ee [file] [log] [blame] [view]
# Profiling CPU Usage
`ffx profiler` is an experimental tool that allows you to find and visualize
hotspots in your code. The CPU profiler periodically samples your running
threads and records backtraces, which can be viewed with the
[`pprof`](https://github.com/google/pprof){:.external} tool.
## Tutorial
To enable and use the CPU profiler in your Fuchsia environment,
do the following:
1. Add some extra arguments to your Fuchsia configuration using the
`fx set` command, for example:
```posix-terminal
fx set <PRODUCT>.<BOARD> \
--release \
--args='experimental_thread_sampler_enabled=true'
```
- `experimental_thread_sampler_enabled=true` enables experimental kernel assisted sampling
support which significantly reduces the overhead of sampling.
Note: Adding the `--release` flag may result in more difficult to follow
stacks due to inlining and optimization passes. However, it will give overall
more representative samples. Especially for Rust and C++ based targets, the
zero cost abstractions in their standard libraries are not zero cost unless
some level of optimization is applied.
2. Interact with the CPU profiler using the `ffx profiler` command,
for example:
```posix-terminal
ffx profiler attach --pids <TARGET_PID> --duration 5
```
This command profiles `<TARGET_PID>` for 5 seconds, then creates
a `profile.pb` file in your current directory, which can be handed to
the `pprof` tool.
3. Use `pprof` to export to various format, including text and interactive
Flame graph, for example:
```posix-terminal
pprof -top profile.pb
```
This command produces output similar to the following:
```none {:.devsite-disable-click-to-copy}
Main binary filename not available.
Type: location
Showing nodes accounting for 272, 100% of 272 total
flat flat% sum% cum cum%
243 89.34% 89.34% 243 89.34% count(int)
17 6.25% 95.59% 157 57.72% main()
4 1.47% 97.06% 4 1.47% collatz(uint64_t*)
3 1.10% 98.16% 3 1.10% add(uint64_t*)
3 1.10% 99.26% 3 1.10% sub(uint64_t*)
1 0.37% 99.63% 1 0.37% rand()
1 0.37% 100% 1 0.37% <unknown>
0 0% 100% 157 57.72% __libc_start_main(zx_handle_t, int (*)(int, char**, char**))
0 0% 100% 154 56.62% _start(zx_handle_t)
0 0% 100% 160 58.82% start_main(const start_params*)
```
## Start and attach to targets
### Pids, Tids, and Job Ids
The easiest way to to get started is to attach to `koids`:
```posix-terminal
ffx profiler attach --duration 5 --pids 123,1234,234 --tids 345,234 --job-ids 123
```
This command attaches to all of the specified `pids`, `tids`, and `job_ids`.
If `pids` are specified, the profiler also attaches to each thread in the process.
If `job_ids` are specified, the profiler attaches to each process and thread in
the job and also attaches to each child job and each process and thread in the
child jobs.
If you dont know your `pid`, you can try identifying it with the following
command:
```posix-terminal
ffx target ssh ps | grep fuchsia_microbenchmarks
```
### Components
The profiler can attach to an existing component using its moniker or URL,
for example:
```posix-terminal
ffx profiler attach --moniker core/ffx-laboratory:your_component
```
```posix-terminal
ffx profiler attach --url 'fuchsia-pkg://fuchsia.com/your_component#meta/your_component.cm'
```
The profiler can also launch your component and attach to it as soon as
it is ready, for example:
```posix-terminal
ffx profiler launch --duration 5 --url 'fuchsia-pkg://fuchsia.com/your_component#meta/your_component.cm'
```