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实现。

相关推荐
测试者家园4 小时前
慢查询日志在性能优化中的价值
sql·性能优化·性能测试·慢查询·持续测试·智能化测试
鼠鼠我捏,要死了捏8 小时前
基于Spring WebFlux的高并发响应式系统性能优化实践指南
性能优化·reactive·spring webflux
十盒半价12 小时前
React 性能优化秘籍:从渲染顺序到组件粒度
react.js·性能优化·trae
Tans518 小时前
裁剪 JVM/Android HPROF 内存快照文件
android·性能优化
转转技术团队20 小时前
MyBatis拦截器在服务内存防护场景中的应用
java·性能优化·mybatis
格发许可优化管理系统1 天前
GTSuite许可证性能优化建议
大数据·运维·数据库·安全·性能优化·数据分析
Code季风1 天前
Spring IoC 容器性能提升指南:启动速度与运行效率优化策略
java·spring·性能优化
鼠鼠我捏,要死了捏1 天前
Elasticsearch索引设计与性能优化实战指南
elasticsearch·性能优化·索引设计
小羊斩肖恩1 天前
Go性能优化深度指南:从原理到实战
开发语言·性能优化·golang
码界奇点2 天前
Java同步锁性能优化:15个高效实践与深度解析
java·开发语言·性能优化·java-ee·同态加密