问题描述
-
我通过以下命令从 Android 设备(内核 4.9)获取
perf.data
:simpleperf record -p 291 -o /data/local/tmp/perf.data --duration 5 -g -f 22750
-
将
perf.data
解析为perf.html
report_html.py report_html.py -i perf.data -o perf.html
-
检查
mmc_blk_end_queued_req
函数在perf.html
。我无法获得正确的流程mmc_blk_end_queued_req
。堆栈应该是mmc_blk_end_queued
→req_bio_endio
→bio_end
,但是mmc_blk_end_queued
→bio_end
来自火焰图。
看看这里:
解决方法
我想我明白了。合并堆栈应该更简单,因为堆栈具有相同的指令指针(ip)和堆栈指针(sp)。
来自Simpleperf:
为什么我们不能总是获得完整的基于 DWARF 的调用图
基于 DWARF 的调用图是通过展开线程堆栈生成的。生成样本时,内核会转储多达 64 KB 的堆栈数据。通过基于 dwarf 信息展开堆栈,我们得到一个调用链。但是线程堆栈可能比 64 KB 长得多。在这种情况下,我们无法展开到线程起点。
为了缓解这个问题,simpleperf 在记录它们之后加入调用链。如果一个线程的两个调用链有一个包含相同 ip 和 sp 地址的条目,那么 simpleperf 会尝试加入它们以使调用链更长。在这种情况下,我们运行的时间越长,我们得到的样本就越多。这使得它更有可能获得完整的调用链,但仍不能保证获得完整的调用图。