基于处理器事件的采样processor event based sampling PEBS 是CPU的另一种非常有用的特性,PEBS被用来在每个采样点获取更多的补充数据。在Intel处理器中,PEBS是在NetBrust微架构开始i引入的,在AMD处理器中,类似的特性叫基于指令的采样IBS。
这些补充数据有定义好的格式,为PEBS配置性能计数器之后,处理器会保存PEBS缓冲区的内容,并将之转存到内存中。记录的信息包括处理器的架构状态,例如,通用的寄存器,EAX, EBX, ESP等,指令指针寄存器EIP和标志寄存器EFLAGS 等的状态,
用户可以通过dmesg命令来检查PEBS是否启用。
字节偏移 字段 字节偏移 字段
EFLAGS R11
EIP R12
RAX R13
EBX R14
ECX R15
EDX
ESI
EDI
EBP
ESP
linux perf工具没像处理LBR那样把原始的PEBS内容导出来,它基于具体需要处理PEBS记录并只导出部分数据。所以,不可能通过linux perf工具导出原始PEBS数据。linux perf工具只提供一些从原始采样数据处理后的PEBS数据,可以通过命令perf report -D获得。要获得原始PEBS记录,可以使用pebs-grabber 工具。
6.3.1 精准事件
当出现溢出导致的中断时,处理器需要一定的时间来停止执行并标记触发溢出的指令。这对现代复杂的乱序执行CPU架构来说,实现起来非常困难。
引入滑动概念,被定义为触发性能事件的IP与标记事件的IP在PEBS记录的IP字段间的距离。滑动使得寻找导致性能问题的指令变得困难,实际上会造成性能问题。想象一个缓存未命中次数很多的程序,热点汇编代码如下load1,load2,load3 性能剖析工具将load3识别为导致高缓存未命中的指令。然而实际上load1才是,通常,这会给新手带来很多困惑,感兴趣的读者可以在intel Developer Zone website找到这类问题潜在的原因的更多信息。
滑动的问题通过让处理器自身记录PEBS记录中的指令地址得到了缓解。PEBS记录中EventingIP字段表示的就是导致性能事件的指令,需要硬件的支持,并且通过只支持一部分性能事件,这样的事件被称为精准事件。具体微架构的精准事件详见,下面列出了Skylake 微架构的精确事件。
INST_RETIRED
OTHER_ASSISTS
BR_INST_RETIRED
BR_MISP_RETIRED
FRONTEND_RETIRED
HLE_RETIRED
RTM_RETIRED
MEM_INST_RETIRED
MEM_LOAD_RETIRED
MEM_LOAD_L3_HIT_RETIRED
TMA分析方法严重依赖精准事件来定位低效率执行代码的具体位置。
easyperf 博客的一篇文章介绍了使用精准事件缓解滑动的例子。linux perf工具的用户需要在事件后面增加ppp后缀来启动精准标注。
perf record -e cpu/event=0xd1
6.3.2 降低采样开销
频繁产生中断并让分析工具采集被中断服务过程中的程序状态,都需要与操作系统交互,这会消化非常多系统资源。这也是为何有些硬件允许无中断的自动对特定的缓冲区采样多次。只有当特定的缓冲区满了,处理器才会发起中断把缓冲区内容刷新到内存中。这种方式的开销相比传统的基于中断的采样开销要低。
为PEBS配置性能计数器后,计数器的溢出条件会支撑PEBS机制,对溢出后的事件,处理器会生成PEBS事件。在PEBS事件中,处理器会把PEBS记录存储到PEBS缓冲区,然后清理计数器溢出状态并恢复到初始值。如果缓冲区满了,CPU将发起一次中断
注意,PEBS缓冲区位于主存内,大小可以设置,性能分析工具的工作时分配和配置内存区域,供CPU导出PEBS记录。
6.3.3 分析内存访问
内存访问时很多应用程序性能的关键因素,有了PEBS,就有可能收集程序中的内存访问相关的详细信息,数据地址剖析可以实现这个功能。为了提供被采样加载和存储指令的更多信息,利用了PEBS特性中的如下字段,
数据线性地址0x98
数据源编码0xa0
时延值 0xA8
如果性能事件支持数据线性地址功能并且启用了该功能,CPU会导出被采样内存访问的地址和时延。请注意,这个功能不会记录所有的存储和加载指令,否则会开销非常大。所以,它只是对内存访问进行采样,例如,大概只会分析1000次访问中的一次,你可以根据需要设置每秒的采样次数。
PEBS扩展的重要使用场景之一的就是检测真伪共享,linux perf 工具严重依赖DLA数据来寻找有争议,可能导致真伪共享内存访问,
此外有了数据地址剖析工具的帮助,用户可以获得程序中内存访问的一般统计信息:
从上面的输出,我们可以看到程序的加载指令有8%通过L1缓存实现,15%通过 DRAM实现。