现代Intel CPU和AMD CPU都有一个叫做最后分支记录的特性,我们可以大段的忽略基本块中的其他指令,因为分支跳转指令总是基本块中最后一条指令。实际上,这是Intel处理器的跟踪PT技术做的,LBR早于PT,使用上有区别。
我们可以使用LBR对分支跳转指令进行采样,但是每次采样期间都需要查看LBR栈中已经执行过的分支跳转指令。这可以实现比较合理的热点代码路径控制流覆盖度,并且也不会采集太多无用的信息,因为所有分支跳转指令中只有很小的一部分会被检查。需要重点注意的是,依然是采样,并不是所有被执行分支跳转指令都能被检查到,通常CPU执行得太快以至于LBR有时并不能正常工作。
(1)最后分支记录LBR栈 Skylake系列CPU提供32对MSR,用于记录最近执行的分支跳转指令的起点和终点
(2)最后分支记录栈顶 LBR中包含一个指向MSR的指针,MSR中包含了最近记录的分支跳转指令,中断和异常信息。
需要注意的是,LBR机制只会记录分支跳转指令信息,下面是一个例子。介绍了LBR栈中分支跳转指令和如何呗跟踪记录的。
mov edi,DWORD PTR [rbx]
test edi,edi
jns 4edale
mov eax,edi
shl eax, 0x7
lea edi, [rax + rdi * 8]
call 4edb26
add rbx, 0x4
mov DWORD PTR [rbx+0x4],eax
cmp rbx,rbp
jne 4eda10
下面是执行CALL指令时我们期望在LBR栈中看到的,因为JNS分之没有被执行,所以不会呗记录,也不会出现的LBR栈中。
从Haswell架构开始,LBR条目中增加了检测分支预测错误的组件,即LBR条目中有一个专用位来标记该信息。从Skylake系列开始,又在LBR条目中添加了LBR_INF组件,有个Cycle Count字段,可以用来记录从最近一次更新LBR栈开始的时钟计数。
使用linux perf工具,我们可用如下命令采集LBR栈
LBR栈也可以使用命令perf record--call-graph lbr采集,但是采集信息量要比命令perf record -b少。命令perf record--call-graph lbr采集不到分支预测错误和时钟周期的数据。
因为每次采样都会捕捉完整的LBR栈,所以所采集 数据perf.data的大小明星比没有启用LBR的时候大很多。
perf script -F brstack
LBR有很多重要的使用场景,下面我们将讨论最重要的几个场景。
我们在5,4,3 节讨论如何采集调用图以及它的重要性,即使在编译程序时没有带帧指针(通过编译选项-fomit-frame-pointer控制,)或调试信息LBR也可以采集调用图信息。
perf record --call-graph lbr -- ./a.exe
perf report -n --stdio
main foo zoo
从上面的信息可以看到,我们识别出了程序中最热的函数bar。外层调用函数foo绝大部份时间都花在了函数bar上了。我们可以看到91%的采样都在函数foo调用的函数bar上。
使用LBR特性,我们可以识别超级块,所谓超级快就是整个程序中一条执行最频繁的基本块链条。链条中的基本块在物理上不一定连续,但是在执行顺序上是连续的。
LBR还可以识别最频繁选取的分支
perf report -e cycles -b -- ./a.exe
perf record Woken up 3 times to write data
从这个例子可以看到,50%以上的分支选取自函数bar内部,20%是函数foo到函数bar的调用,其他的以此类推,注意perf工具从cycles事件到分析LBR栈的变化,虽然只有670个样本,每个样本都有一个完整的LBR栈,这样就有
67x32 = 21440个LBR条目待分析。
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- awee.cn 版权所有 湘ICP备2023022495号-5
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务