CPU性能优化--基于处理器事件的采样

基于处理器事件的采样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实现。

相关推荐
Amd79412 小时前
索引的性能影响:优化数据库查询与存储的关键
性能优化·数据库管理·存储空间·查询性能·数据库索引·系统资源·更新性能
桦说编程14 小时前
【异步编程实战】如何实现超时功能(以CompletableFuture为例)
java·性能优化·函数式编程·并发编程
John_ToDebug18 小时前
chrome源码剖析—UI架构&&消息机制
c++·chrome·性能优化
美狐美颜sdk21 小时前
美颜技术开发实战:美颜滤镜SDK的性能优化与兼容性解决方案
人工智能·深度学习·性能优化·美颜sdk·第三方美颜sdk·视频美颜sdk
xidianjiapei0011 天前
优化性能:高性能云计算的虚拟化技术
性能优化·云计算·虚拟化·高性能计算
思逻辑维2 天前
激活版,快速安装
人工智能·性能优化·电脑·硬件工程
Zda天天爱打卡2 天前
【趣学SQL】第五章:性能优化与调优 5.1 查询性能优化——让数据库跑得比外卖小哥还快的秘籍
数据库·sql·性能优化
Zda天天爱打卡2 天前
【趣学SQL】第五章:性能优化与调优 5.2 数据库调优——让MySQL跑得比双十一快递还快的终极秘籍
数据库·sql·性能优化
亦黑迷失4 天前
vue 项目优化之函数式组件
前端·vue.js·性能优化