xref: /aosp_15_r20/system/extras/simpleperf/doc/android_platform_profiling.md (revision 288bf5226967eb3dac5cce6c939ccc2a7f2b4fe5)
1# Android platform profiling
2
3[TOC]
4
5## General Tips
6
7Here are some tips for Android platform developers, who build and flash system images on rooted
8devices:
91. After running `adb root`, simpleperf can be used to profile any process or system wide.
102. It is recommended to use the latest simpleperf available in AOSP main, if you are not working
11on the current main branch. Scripts are in `system/extras/simpleperf/scripts`, binaries are in
12`system/extras/simpleperf/scripts/bin/android`.
133. It is recommended to use `app_profiler.py` for recording, and `report_html.py` for reporting.
14Below is an example.
15
16```sh
17# Record surfaceflinger process for 10 seconds with dwarf based call graph. More examples are in
18# scripts reference in the doc.
19$ ./app_profiler.py -np surfaceflinger -r "-g --duration 10"
20
21# Generate html report.
22$ ./report_html.py
23```
24
254. Since Android >= O has symbols for system libraries on device, we don't need to use unstripped
26binaries in `$ANDROID_PRODUCT_OUT/symbols` to report call graphs. However, they are needed to add
27source code and disassembly (with line numbers) in the report. Below is an example.
28
29```sh
30# Doing recording with app_profiler.py or simpleperf on device, and generates perf.data on host.
31$ ./app_profiler.py -np surfaceflinger -r "--call-graph fp --duration 10"
32
33# Collect unstripped binaries from $ANDROID_PRODUCT_OUT/symbols to binary_cache/.
34$ ./binary_cache_builder.py -lib $ANDROID_PRODUCT_OUT/symbols
35
36# Collect unstripped binaries from symbol file downloaded from builder server to binary_cache/.
37$ unzip comet-symbols-12488474.zip
38$ ./binary_cache_builder.py -lib out
39
40# To verify that the binaries in binary_cache/ include debug sections, you can perform a manual
41# check.
42
43# Generate an HTML report with source code and disassembly.
44# Disassembling all binaries can be slow, so you can use the --binary_filter
45# option to disassemble only specific binaries, like surfaceflinger.so in this example.
46$ ./report_html.py --add_source_code --source_dirs $ANDROID_BUILD_TOP --add_disassembly \
47  --binary_filter surfaceflinger.so
48```
49
50For a comprehensive guide to displaying source code and disassembly, see
51[Show Annotated Source Code and Disassembly](README.md#show-annotated-source-code-and-disassembly).
52
53
54## Start simpleperf from system_server process
55
56Sometimes we want to profile a process/system-wide when a special situation happens. In this case,
57we can add code starting simpleperf at the point where the situation is detected.
58
591. Disable selinux by `adb shell setenforce 0`. Because selinux only allows simpleperf running
60   in shell or debuggable/profileable apps.
61
622. Add below code at the point where the special situation is detected.
63
64```java
65try {
66  // for capability check
67  Os.prctl(OsConstants.PR_CAP_AMBIENT, OsConstants.PR_CAP_AMBIENT_RAISE,
68           OsConstants.CAP_SYS_PTRACE, 0, 0);
69  // Write to /data instead of /data/local/tmp. Because /data can be written by system user.
70  Runtime.getRuntime().exec("/system/bin/simpleperf record -g -p " + String.valueOf(Process.myPid())
71            + " -o /data/perf.data --duration 30 --log-to-android-buffer --log verbose");
72} catch (Exception e) {
73  Slog.e(TAG, "error while running simpleperf");
74  e.printStackTrace();
75}
76```
77
78## Hardware PMU counter limit
79
80When monitoring instruction and cache related perf events (in hw/cache/raw/pmu category of list cmd),
81these events are mapped to PMU counters on each cpu core. But each core only has a limited number
82of PMU counters. If number of events > number of PMU counters, then the counters are multiplexed
83among events, which probably isn't what we want. We can use `simpleperf stat --print-hw-counter` to
84show hardware counters (per core) available on the device.
85
86On Pixel devices, the number of PMU counters on each core is usually 7, of which 4 of them are used
87by the kernel to monitor memory latency. So only 3 counters are available. It's fine to monitor up
88to 3 PMU events at the same time. To monitor more than 3 events, the `--use-devfreq-counters` option
89can be used to borrow from the counters used by the kernel.
90
91## Get boot-time profile
92
93On userdebug/eng devices, we can get boot-time profile via simpleperf.
94
95Step 1. Customize the configuration if needed. By default, simpleperf tracks all processes
96except for itself, starts at `early-init`, and stops when `sys.boot_completed` is set.
97You can customize it by changing the trigger or command line flags in
98`system/extras/simpleperf/simpleperf.rc`.
99
100Step 2. Add `androidboot.simpleperf.boot_record=1` to the kernel command line.
101For example, on Pixel devices, you can do
102```
103$ fastboot oem cmdline add androidboot.simpleperf.boot_record=1
104```
105
106Step 3. Reboot the device. When booting, init finds that the kernel command line flag is set,
107so it forks a background process to run simpleperf to record boot-time profile.
108init starts simpleperf at `early-init` stage, which is very soon after second-stage init starts.
109
110Step 4. After boot, the boot-time profile is stored in /tmp/boot_perf.data. Then we can pull
111the profile to host to report.
112
113```
114$ adb shell ls /tmp/boot_perf.data
115/tmp/boot_perf.data
116```
117
118Following is a boot-time profile example. From timestamp, the first sample is generated at about
1194.5s after booting.
120
121![boot_time_profile](pictures/boot_time_profile.png)
122