Simpleperf分析之Android系統篇

【譯】Simpleperf分析之Android系統篇

譯者按:

Simpleperf是用於Native的CPU性能分析工具,主要用來分析代碼執行耗時。本文是主文檔的一部分,系統篇。

原文見aosp倉庫:android_platform_profiling.md

Simpleperf主文檔見aosp倉庫:Simpleperf

官網介紹://developer.android.com/ndk/guides/simpleperf

目錄

通用技巧

這裡有一些技巧給有root權限的Android系統開發者:

  1. 運行 adb root後, simpleperf可用於分析系統範圍內任何進程。
  2. 如果不是在主分支上工作,建議使用AOSP main中最新的simpleperf。腳本位置在 system/extras/simpleperf/scripts,二進制程序在system/extras/simpleperf/scripts/bin/android.
  3. 推薦使用 app_profiler.py 抓trace,然後用 report_html.py 生成html報告。 下面是一個示例。
# Record surfaceflinger process for 10 seconds with dwarf based call graph. More examples are in
# scripts reference in the doc.
$ python app_profiler.py -np surfaceflinger -r "-g --duration 10"

# Generate html report.
$ python report_html.py
  1. 從 Android >= O 開始系統庫默認有符號表,我們不需要用$ANDROID_PRODUCT_OUT/symbols 中未striped二進制文件來抓了。 但是,在報告中添加源代碼和反彙編(帶有行號)時需要它們。下面是一個例子。
# Doing recording with app_profiler.py or simpleperf on device, and generates perf.data on host.
$ python app_profiler.py -np surfaceflinger -r "--call-graph fp --duration 10"

# Collect unstripped binaries from $ANDROID_PRODUCT_OUT/symbols to binary_cache/.
$ python binary_cache_builder.py -lib $ANDROID_PRODUCT_OUT/symbols

# Report source code and disassembly. Disassembling all binaries is slow, so it's better to add
# --binary_filter option to only disassemble selected binaries.
$ python report_html.py --add_source_code --source_dirs $ANDROID_BUILD_TOP --add_disassembly \
  --binary_filter surfaceflinger.so

在system_server進程上抓simpleperf

有時我們希望在發生特殊情況時抓系統進程。在這種情況下,我們可以在檢測到情況的點處添加SimplEperf的代碼。

  1. 關掉selinux adb shell setenforce 0。因為selinux只允許simpleperf在shell或debuggable/profileable 應用中使用。
  2. 在檢測到特殊情況的地方添加下面的代碼。
try {
  // for capability check
  Os.prctl(OsConstants.PR_CAP_AMBIENT, OsConstants.PR_CAP_AMBIENT_RAISE,
           OsConstants.CAP_SYS_PTRACE, 0, 0);
  // Write to /data instead of /data/local/tmp. Because /data can be written by system user.
  Runtime.getRuntime().exec("/system/bin/simpleperf record -g -p " + String.valueOf(Process.myPid())
            + " -o /data/perf.data --duration 30 --log-to-android-buffer --log verbose");
} catch (Exception e) {
  Slog.e(TAG, "error while running simpleperf");
  e.printStackTrace();
}

硬件 PMU 計數器限制

監視指令和緩存相關的性能事件時 (在list命令列出的hw/cache/raw/pmu 類別),這些事件被映射到每個cpu核心上的PMU計數器。但每個核心只有有限數量的PMU計數器。如果事件數量 > PMU計數器的數量,然後計數器在事件之間多路復用,這可能不是我們想要的。

在Pixel設備上,每個核上的PMU計數器的數量通常是7個,其中4個被內核用於監視內存延遲。所以只有3個計數器可用。可以同時監控最多3個PMU事件。要監視3個以上的事件,可以使用 --use-devfreq-counters 選項借用內核使用的計數器。