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# Report source code and disassembly. Disassembling all binaries is slow, so it's better to add 37# --binary_filter option to only disassemble selected binaries. 38$ ./report_html.py --add_source_code --source_dirs $ANDROID_BUILD_TOP --add_disassembly \ 39 --binary_filter surfaceflinger.so 40``` 41 42## Start simpleperf from system_server process 43 44Sometimes we want to profile a process/system-wide when a special situation happens. In this case, 45we can add code starting simpleperf at the point where the situation is detected. 46 471. Disable selinux by `adb shell setenforce 0`. Because selinux only allows simpleperf running 48 in shell or debuggable/profileable apps. 49 502. Add below code at the point where the special situation is detected. 51 52```java 53try { 54 // for capability check 55 Os.prctl(OsConstants.PR_CAP_AMBIENT, OsConstants.PR_CAP_AMBIENT_RAISE, 56 OsConstants.CAP_SYS_PTRACE, 0, 0); 57 // Write to /data instead of /data/local/tmp. Because /data can be written by system user. 58 Runtime.getRuntime().exec("/system/bin/simpleperf record -g -p " + String.valueOf(Process.myPid()) 59 + " -o /data/perf.data --duration 30 --log-to-android-buffer --log verbose"); 60} catch (Exception e) { 61 Slog.e(TAG, "error while running simpleperf"); 62 e.printStackTrace(); 63} 64``` 65 66## Hardware PMU counter limit 67 68When monitoring instruction and cache related perf events (in hw/cache/raw/pmu category of list cmd), 69these events are mapped to PMU counters on each cpu core. But each core only has a limited number 70of PMU counters. If number of events > number of PMU counters, then the counters are multiplexed 71among events, which probably isn't what we want. We can use `simpleperf stat --print-hw-counter` to 72show hardware counters (per core) available on the device. 73 74On Pixel devices, the number of PMU counters on each core is usually 7, of which 4 of them are used 75by the kernel to monitor memory latency. So only 3 counters are available. It's fine to monitor up 76to 3 PMU events at the same time. To monitor more than 3 events, the `--use-devfreq-counters` option 77can be used to borrow from the counters used by the kernel. 78 79## Get boot-time profile 80 81On userdebug/eng devices, we can get boot-time profile via simpleperf. 82 83Step 1. In adb root, set options used to record boot-time profile. Simpleperf stores the options in 84a persist property `persist.simpleperf.boot_record`. 85 86``` 87# simpleperf boot-record --enable "-a -g --duration 10 --exclude-perf" 88``` 89 90Step 2. Reboot the device. When booting, init finds that the persist property is set, so it forks 91a background process to run simpleperf to record boot-time profile. init starts simpleperf at 92zygote-start stage, right after zygote is started. 93 94``` 95$ adb reboot 96``` 97 98Step 3. After boot, the boot-time profile is stored in /data/simpleperf_boot_data. Then we can pull 99the profile to host to report. 100 101``` 102$ adb shell ls /data/simpleperf_boot_data 103perf-20220126-11-47-51.data 104``` 105 106Following is a boot-time profile example. From timestamp, the first sample is generated at about 1074.5s after booting. 108 109 110