我没有通过 simpleperf 正确获取内核堆栈

问题描述

  1. 我通过以下命令从 Android 设备(内核 4.9)获取 perf.data

    simpleperf record -p 291 -o /data/local/tmp/perf.data --duration 5 -g -f 22750
    
  2. perf.data 解析为 perf.html

    report_html.py report_html.py -i perf.data -o perf.html
    
  3. 检查 mmc_blk_end_queued_req 函数perf.html。我无法获得正确的流程

    mmc_blk_end_queued_req。堆栈应该是 mmc_blk_end_queuedreq_bio_endiobio_end,但是 mmc_blk_end_queuedbio_end 来自火焰图

看看这里:

Enter image description here

解决方法

我想我明白了。合并堆栈应该更简单,因为堆栈具有相同的指令指针(ip)和堆栈指针(sp)。


来自Simpleperf

为什么我们不能总是获得完整的基于 DWARF 的调用图

基于 DWARF 的调用图是通过展开线程堆栈生成的。生成样本时,内核会转储多达 64 KB 的堆栈数据。通过基于 dwarf 信息展开堆栈,我们得到一个调用链。但是线程堆栈可能比 64 KB 长得多。在这种情况下,我们无法展开到线程起点。

为了缓解这个问题,simpleperf 在记录它们之后加入调用链。如果一个线程的两个调用链有一个包含相同 ip 和 sp 地址的条目,那么 simpleperf 会尝试加入它们以使调用链更长。在这种情况下,我们运行的时间越长,我们得到的样本就越多。这使得它更有可能获得完整的调用链,但仍不能保证获得完整的调用图。