Perfetto使用教程

Perfetto 是谷歌開發(fā)的用于性能檢測和跟蹤分析的生產(chǎn)級(jí)開源堆棧。它提供用于記錄系統(tǒng)級(jí)和應(yīng)用程序級(jí)跟蹤的服務(wù)和庫,包括本機(jī) + Java堆分析,使用SQL分析跟蹤數(shù)據(jù)的C++庫以及基于Web的可視化UI,能夠清晰地展示GB級(jí)別體量的跟蹤數(shù)據(jù)。Perfetto 適用于Linux內(nèi)核和Android的整個(gè)系統(tǒng)范圍內(nèi)的性能數(shù)據(jù)收集、可視化及數(shù)據(jù)分析。


開啟設(shè)備追蹤

Android 11 (R)及以上默認(rèn)開啟Perfetto,Android 9 (P)和10 (Q) 需要手動(dòng)開啟,其他設(shè)備暫不支持:

# Needed only on Android 9 (P) and 10 (Q) on non-Pixel phones.
adb shell setprop persist.traced.enable 1

啟動(dòng)抓取方式

通過腳本工具tools/record_android_trace,使用命令行工具啟動(dòng)設(shè)備抓取

 adb shell perfetto [ --time TIMESPEC ] [ --buffer SIZE ] [ --size SIZE ]
    [ ATRACE_CAT | FTRACE_GROUP/FTRACE_NAME]...

通過抓取頁面Perfetto UI

Perfetto UI抓取簡介

Recording settings

三種錄制設(shè)置,適用不同的使用場景

Stop when full

  • in-memory buffer size
    設(shè)置存儲(chǔ)trace的最大buffer大小,存儲(chǔ)在內(nèi)存中,不會(huì)影響到IO。
  • Max duration
    設(shè)置此次 trace 抓取的最大時(shí)長
    該模式下Perfetto的停止受buffer大小和trace時(shí)長的控制,滿足兩個(gè)任意條件之一,即可停止trace。
    優(yōu)點(diǎn):trace不會(huì)因?yàn)閛verwrite而導(dǎo)致丟失。
    缺點(diǎn):如果trace太多,會(huì)導(dǎo)致提前結(jié)束,無法錄制到出現(xiàn)問題時(shí)候的trace。


Ring buffer

該模式只會(huì)收到Max duration的影響,時(shí)間到了就停止抓取trace,但是trace會(huì)有被overwrite的風(fēng)險(xiǎn)。


Long trace

用于長時(shí)間地抓取trace,但是由于需要定時(shí)將buffer中的trace寫到文件里面去,會(huì)有IO的影響。
Flush on disk every
間隔多長時(shí)間將buffer中的trace寫入到文件,這個(gè)數(shù)值不能太大也不能太小,太大容易丟trace,太小容易出現(xiàn)IO問題。trace的停止主要受控于Max duration,或者手動(dòng)停止。


CPU

CPU相關(guān)的常見功能統(tǒng)計(jì)


  • Coarse CPU usage counter
    粗粒度的CPU相關(guān)使用統(tǒng)計(jì)
  • Scheduling details
    詳細(xì)查看CPU運(yùn)行的每個(gè)task


  • CPU frequency and idle states
    查看每顆CPU的運(yùn)行頻率和是否空閑


  • Syscalls
    記錄每一個(gè)系統(tǒng)調(diào)用,對性能影響較大,需要userdebug版本。

GPU

記錄GPU的主頻和內(nèi)存使用


  • GPU frequency
    記錄GPU的頻率


  • GPU memory
    GPU內(nèi)存使用量及各個(gè)進(jìn)程的占用,僅支持Android 12+


Power

Memory

Android apps & svcs

  • Atrace userspace annotations
    開啟這個(gè)選項(xiàng)之后,選擇合適的atrace tag就可以開啟對應(yīng)的trace了,這個(gè)tag就對應(yīng)了System Tracing的界面的catergray。
  • Event log (logcat)
    可以實(shí)時(shí)記錄log,然后將log和trace信息一一對應(yīng)。 選擇合適的log類型,就可以記錄相應(yīng)的log。


Chrome

如果需要分析webview相關(guān)的性能問題,可以開啟該選項(xiàng)的相關(guān)功能


Stack Samples

  • Callstack sampling
    定期記錄進(jìn)程的當(dāng)前函數(shù)調(diào)用堆棧

Advanced settings

目前只有一個(gè)開啟ftrace功能,用于分析內(nèi)核性能問題,可以選擇相應(yīng)的tag進(jìn)行記錄


Recording command

配置匯總和執(zhí)行,完成上述參數(shù)配置后,可以在改選項(xiàng)中獲得所有的配置參數(shù),拷貝命令,直接adb開啟錄制追蹤。


adb shell perfetto \
  -c - --txt \
  -o /data/misc/perfetto-traces/trace \
<<EOF

buffers: {
    size_kb: 63488
    fill_policy: DISCARD
}
buffers: {
    size_kb: 2048
    fill_policy: DISCARD
}
data_sources: {
    config {
        name: "android.packages_list"
        target_buffer: 1
    }
}
data_sources: {
    config {
        name: "android.log"
        android_log_config {
            log_ids: LID_KERNEL
            log_ids: LID_DEFAULT
            log_ids: LID_RADIO
            log_ids: LID_SECURITY
            log_ids: LID_STATS
            log_ids: LID_SYSTEM
        }
    }
}
data_sources: {
    config {
        name: "linux.perf"
        perf_event_config {
            timebase {
                frequency: 100
                timestamp_clock: PERF_CLOCK_BOOTTIME
            }
            callstack_sampling {
            }
        }
    }
}
data_sources: {
    config {
        name: "org.chromium.trace_event"
        chrome_config {
            trace_config: "{\"record_mode\":\"record-until-full\",\"included_categories\":[\"accessibility\",\"audio\",\"aogh\",\"android_webview.timeline\",\"android_webview\",\"disabled-by-default-audio-worklet\",\"disabled-by-default-animation-worklet\",\"disabled-by-default-blink.debug\",\"log\",\"toplevel\",\"toplevel.flow\",\"scheduler\",\"sequence_manager\",\"disabled-by-default-toplevel.flow\",\"disabled-by-default-ipc.flow\",\"mojom\",\"v8\",\"blink\",\"cc\",\"gpu\",\"viz\",\"ui\",\"views\",\"benchmark\",\"evdev\",\"input\",\"loading\",\"net\",\"netlog\",\"navigation\",\"browser\"],\"excluded_categories\":[\"*\"],\"memory_dump_config\":{}}"
            privacy_filtering_enabled: true
            client_priority: USER_INITIATED
        }
    }
}
data_sources: {
    config {
        name: "track_event"
        chrome_config {
            trace_config: "{\"record_mode\":\"record-until-full\",\"included_categories\":[\"accessibility\",\"audio\",\"aogh\",\"android_webview.timeline\",\"android_webview\",\"disabled-by-default-audio-worklet\",\"disabled-by-default-animation-worklet\",\"disabled-by-default-blink.debug\",\"log\",\"toplevel\",\"toplevel.flow\",\"scheduler\",\"sequence_manager\",\"disabled-by-default-toplevel.flow\",\"disabled-by-default-ipc.flow\",\"mojom\",\"v8\",\"blink\",\"cc\",\"gpu\",\"viz\",\"ui\",\"views\",\"benchmark\",\"evdev\",\"input\",\"loading\",\"net\",\"netlog\",\"navigation\",\"browser\"],\"excluded_categories\":[\"*\"],\"memory_dump_config\":{}}"
            privacy_filtering_enabled: true
            client_priority: USER_INITIATED
        }
        track_event_config {
            disabled_categories: "*"
            enabled_categories: "accessibility"
            enabled_categories: "audio"
            enabled_categories: "aogh"
            enabled_categories: "android_webview.timeline"
            enabled_categories: "android_webview"
            enabled_categories: "disabled-by-default-audio-worklet"
            enabled_categories: "disabled-by-default-animation-worklet"
            enabled_categories: "disabled-by-default-blink.debug"
            enabled_categories: "log"
            enabled_categories: "toplevel"
            enabled_categories: "toplevel.flow"
            enabled_categories: "scheduler"
            enabled_categories: "sequence_manager"
            enabled_categories: "disabled-by-default-toplevel.flow"
            enabled_categories: "disabled-by-default-ipc.flow"
            enabled_categories: "mojom"
            enabled_categories: "v8"
            enabled_categories: "blink"
            enabled_categories: "cc"
            enabled_categories: "gpu"
            enabled_categories: "viz"
            enabled_categories: "ui"
            enabled_categories: "views"
            enabled_categories: "benchmark"
            enabled_categories: "evdev"
            enabled_categories: "input"
            enabled_categories: "loading"
            enabled_categories: "net"
            enabled_categories: "netlog"
            enabled_categories: "navigation"
            enabled_categories: "browser"
            enabled_categories: "__metadata"
            timestamp_unit_multiplier: 1000
            filter_debug_annotations: true
            enable_thread_time_sampling: true
            filter_dynamic_event_names: true
        }
    }
}
data_sources: {
    config {
        name: "org.chromium.trace_metadata"
        chrome_config {
            trace_config: "{\"record_mode\":\"record-until-full\",\"included_categories\":[\"accessibility\",\"audio\",\"aogh\",\"android_webview.timeline\",\"android_webview\",\"disabled-by-default-audio-worklet\",\"disabled-by-default-animation-worklet\",\"disabled-by-default-blink.debug\",\"log\",\"toplevel\",\"toplevel.flow\",\"scheduler\",\"sequence_manager\",\"disabled-by-default-toplevel.flow\",\"disabled-by-default-ipc.flow\",\"mojom\",\"v8\",\"blink\",\"cc\",\"gpu\",\"viz\",\"ui\",\"views\",\"benchmark\",\"evdev\",\"input\",\"loading\",\"net\",\"netlog\",\"navigation\",\"browser\"],\"excluded_categories\":[\"*\"],\"memory_dump_config\":{}}"
            privacy_filtering_enabled: true
            client_priority: USER_INITIATED
        }
    }
}
data_sources: {
    config {
        name: "android.heapprofd"
        target_buffer: 0
        heapprofd_config {
            sampling_interval_bytes: 4096
            continuous_dump_config {
                dump_phase_ms: 30000
                dump_interval_ms: 10000
            }
            shmem_size_bytes: 8388608
            block_client: true
        }
    }
}
data_sources: {
    config {
        name: "linux.ftrace"
        ftrace_config {
            ftrace_events: "clk/*"
            ftrace_events: "ext4/*"
            ftrace_events: "f2fs/*"
            ftrace_events: "fastrpc/*"
            ftrace_events: "i2c/*"
            ftrace_events: "irq/*"
            ftrace_events: "kmem/*"
            ftrace_events: "memory_bus/*"
            ftrace_events: "mmc/*"
            ftrace_events: "oom/*"
            ftrace_events: "power/*"
            ftrace_events: "regulator/*"
            ftrace_events: "sched/*"
            ftrace_events: "sync/*"
            ftrace_events: "task/*"
            ftrace_events: "ftrace/print"
            atrace_categories: "am"
            atrace_categories: "adb"
            atrace_categories: "aidl"
            atrace_categories: "dalvik"
            atrace_categories: "audio"
            atrace_categories: "binder_lock"
            atrace_categories: "binder_driver"
            atrace_categories: "bionic"
            atrace_categories: "camera"
            atrace_categories: "database"
            atrace_categories: "gfx"
            atrace_categories: "hal"
            atrace_categories: "input"
            atrace_categories: "network"
            atrace_categories: "nnapi"
            atrace_categories: "pm"
            atrace_categories: "power"
            atrace_categories: "rs"
            atrace_categories: "res"
            atrace_categories: "rro"
            atrace_categories: "sm"
            atrace_categories: "ss"
            atrace_categories: "vibrator"
            atrace_categories: "video"
            atrace_categories: "view"
            atrace_categories: "webview"
            atrace_apps: "*"
            buffer_size_kb: 512
            drain_period_ms: 100
        }
    }
}
duration_ms: 40000

EOF

trace 文件獲取

使用 adb pull /data/misc/perfetto-traces/trace ~/trace.perfetto-trace 提取跟蹤日志文件并在 Perfetto UI 中打開它。

trace文件過大加載問題

當(dāng)trace文件大于1G時(shí),Open trace file會(huì)出現(xiàn)oops 內(nèi)存溢出無法訪問。



可以使用Trace Processor來加載trace文件

# Download prebuilts (Linux and Mac only)
curl -LO https://get.perfetto.dev/trace_processor
chmod +x ./trace_processor

# Start the interactive shell
./trace_processor trace.perfetto-trace

# Start a local trace processor instance to replace wasm module in the UI
./trace_processor trace.perfetto-trace --httpd

執(zhí)行./trace_processor trace.perfetto-trace --httpd后,Chrome瀏覽器打開 https://ui.perfetto.dev/#!/ ,會(huì)自動(dòng)檢測本地是否已經(jīng)有trace_processor生成的HTTP SERVER(9001端口),如下圖提示,請選擇“YES, use loaded trace”,將自動(dòng)解析 trace_processor已經(jīng)加載的pftrace文件。

分析方法簡介

slice 片段

對應(yīng)代碼中 Trace.beginSection/ATRACE_BEGIN 記錄的事件,選中后會(huì)顯示黑色邊框


counter

計(jì)數(shù)器,記錄離散的數(shù)值點(diǎn),對應(yīng)代碼中 Trace.beginCounter/ATRACE_INT 記錄的事件


CPU調(diào)度和頻率

線程狀態(tài)

點(diǎn)擊片段上方線程調(diào)度信息片段(Running),可以看到線程當(dāng)前運(yùn)行在哪個(gè)CPU上



點(diǎn)擊箭頭 ,可以在CPU調(diào)度中看到該運(yùn)行片段以及調(diào)度時(shí)延信息。



被P: /system/bin/traced_probes [1488]T: traced_probes [1488]線程喚醒,從就緒到運(yùn)行延遲了 774us 792ns,再次點(diǎn)擊箭頭,可以回到原片段,這個(gè)跳轉(zhuǎn)比較靈活方便。

鎖競爭(lock contention)

在lock contention 片段上,可以點(diǎn)擊上邊的monitor contention來查看當(dāng)前對象鎖競爭發(fā)生的調(diào)用棧,如下詳情中顯示當(dāng)前對象鎖被Owner (Binder:1754_16)持有,其持鎖當(dāng)前運(yùn)行在serviceDoneExecuting (AMS.java 16426行),且當(dāng)前等待該對象鎖的線程已經(jīng)有5個(gè)了;當(dāng)前線程執(zhí)行被阻塞在getUidState方法中(AMS.java 6614行)。


SQL查詢

Perfetto支持通過sql語句查詢數(shù)據(jù),提供常見的格式和關(guān)鍵字段信息:

  • slice表,橫向track上的一條條小片段

  • ts:片段起始時(shí)間戳(單位ns)

  • dur:片段持續(xù)時(shí)長(ns)

  • track_id屬于哪個(gè)track(水平timeline)

  • name: 片段標(biāo)注的名稱,對應(yīng)Trace中打印的方法名、標(biāo)記等信息

  • thread_track表,utid標(biāo)識(shí)線程tid,并不是真實(shí)的線程tid

  • thread表,表示各線程信息,其中utid和thread_track表的utid關(guān)聯(lián)

  • process表,upid和thread表的upid關(guān)聯(lián),表示線程所屬的父進(jìn)程

  • sched_slice,線程調(diào)度片段

  • thread_state,各track上邊的線程調(diào)度片段,標(biāo)識(shí)線程運(yùn)行狀態(tài)

Slices

橫向軸上的一小段時(shí)間片段,具有指定的名稱


> SELECT ts, dur, name FROM slice
ts                   dur                  name
-------------------- -------------------- ---------------------------
     261187017446933               358594 eglSwapBuffersWithDamageKHR
     261187017518340                  357 onMessageReceived
     261187020825163                 9948 queueBuffer
     261187021345235                  642 bufferLoad
     261187121345235                  153 query
     ...

Counters

根據(jù)時(shí)間記錄的離散數(shù)值點(diǎn)



···

SELECT ts, value FROM counter
ts value


 261187012149954          1454.000000
 261187012399172          4232.000000
 261187012447402         14304.000000
 261187012535839         15490.000000
 261187012590890         17490.000000
 261187012590890         16590.000000

...
···

Scheduler slices

CPU運(yùn)行的詳細(xì)task


> SELECT ts, dur, cpu, utid FROM sched
ts                   dur                  cpu                  utid
-------------------- -------------------- -------------------- --------------------
     261187012170489               267188                    0                  390
     261187012170995               247153                    1                  767
     261187012418183                12812                    2                 2790
     261187012421099               220000                    6                  683
     261187012430995                72396                    7                 2791
...

參考文章

1、 https://perfetto.dev/docs/

2、https://ui.perfetto.dev/#!/record

3、https://www.cnblogs.com/treecarrybear/p/17056783.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容