导语:在刚刚结束的全球虚拟化顶级技术峰会 KVM Forum 上,2022 年度全球企业 KVM 开源贡献榜正式发布。腾讯云连续六年入围,并成为贡献值最高的中国企业。其中,腾讯云自研的精确事件采样技术的虚拟化方案,被评为 KVM 年度核心突破。本文将详细介绍该技术背后的实现过程。
什么是Guest PEBS
针对虚拟机中CPU硬件性能事件与软件代码匹配不够准确的问题,腾讯云技术团队经过深入研究和硬件探索,自主设计了Guest PEBS(精确事件采样技术) 特性在KVM上的虚拟化方案。这项技术的独到之处在于,让虚拟机上CPU运行数据从此由“黑盒”变成了“白盒”,云上开发者从此能够随时随地洞察CPU的运行状态和数据。
与常规性能事件计数器溢出中断相比,目标代码的事件指令滑动误差被最小化,同时通过直接将多个性能事件发生时的不同CPU状态批量写入虚拟机内存中,保证了在采集大量性能事件样本时没有即时中断,大幅减小了性能事件采样开销,实现了应用程序内代码级粒度的数据可采集、性能可分析、瓶颈可优化的技术升级。
性能事件精准采样技术实现过程
作为云上开发者,在日常的开发或者运维中,经常需要在安全隔离的虚拟化环境中, 对特定或全局软件负载进行性能数据的量化、瓶颈分析与优化。业界此类需求往往通过额外的软件逻辑定期记录运行状态,手动或自动推理出前后改动的相对性能差异,这依赖于操作系统或应用内预先设定的性能分析回调点,这种方法可以提供一部分性能数据,但是会牺牲一部分性能和准确性。
在基于硬件的性能分析中,开发者往往会借助性能监控单元 (PMU) 以及性能事件计数器 (PMC)。在计算机系统中的几乎每个计算硬件单元(比如 CPU、GPU、FPGA)都有PMU,每个 PMU 往往包含一组固定功能或可选择的性能事件计数器。性能事件计数器是一种基于硬件的性能监测机制,被许多硬件供应商所支持。硬件性能事件是预先定义的,比如 指令缓存缺失的数量(ICACHE.MISSES)或 分支指令数(branch-instructions)。用户可以选择其中的一小部分让执行软件的CPU顺手来计数硬件事件,在事件发生指定次数后,计数器会溢出。每个逻辑CPU都有自己的一组性能事件计数器。这样就可以在每个逻辑核上进行性能事件分析。
1、溢出中断与采样
使用性能计数器进行性能分析是基于中断的。我们初始化一些性能事件计数器并等待它溢出,当一个计数器溢出时,性能监控单元会触发性能监控中断。操作系统收到中断通知后,几乎在触发中断的事件发生时收集被分析的应用程序的信息,即样本。例如,指令缓存缺失的数量达到一定次数后触发了性能监控中断,并在每次调用中断时保存程序指令指针,就可以知道哪个程序、函数、指令导致大量的指令缓存缺失。记录的内容取决于硬件的能力与软件的选择,但所有样本中共有的关键信息是指令指针,即程序被中断时运行在哪里。
2 采样时的指令滑动
开发者已经注意到,基于中断的采样技术即使在现代处理器上也都会引入误差,即指令滑动(skid)。进一步说,存储在每个样本中的指令指针指明了程序被中断以处理性能监控中断的当前位置,但这不一定是性能事件计数器实际溢出是的执行位置,即采样周期结束时的位置。在发出性能监视中断和捕获指令指针之间存在延迟。指令滑动可以定义为"触发性能事件的指令"与"记录样本时的指令"之间的距离。
比如我们现在有一个对 “已确认指令” 事件进行采样的性能计数器溢出,由于在事件生成和溢出中断生成之间的微体系结构中存在延迟,有时难以当场生成接近导致它的性能事件的性能监控中断。因此,在生成中断时,CPU已经往前执行了许多指令在某些情况下,如果有分支,这两个点之间的距离可能是几十条指令或更多。当我们在中断服务程序中重建寄存器状态时,我们的数据有些不准确。性能分析是一件很难的事情,毫无疑问,特别是当开发者被采集到的性能分析样本误导时,它变得更加困难。
3 性能事件精准采样
采样时的指令滑动迫使开发者只能基于经验推断实际上导致性能问题的程序指令。在现代处理器中,我们发现有一些机制专门用来解决这个问题, 在Intel平台上是Precise Event Based Sampling (PEBS)技术,在AMD平台上是Instruction Based Sampling (IBS) 技术。基于事件的精确采样技术是英特尔对于普通性能事件计数器的扩展,处理器会将指令指针(连同其他信息)写入由软件指定的内存缓冲,可以显著缓解指令滑动问题,每个样本都不会发出中断,它的基本工作原理图如下:
用户选择一组事件并指定每个计数器是启用 PEBS,所以PEBS 计数器和普通计数器可以同时使用。CPU 使用为每个事件指定的计数器寄存器来计算指定事件的数量。并不是所有的性能事件都可以用 PEBS,每个微架构都有不同的 PEBS 可使用的事件。
当一个支持 PEBS 的硬件事件计数器溢出时,CPU 会触发一个 PEBS 辅助(而不是调用中断),执行一个预先定义的微代码。该微代码将上下文信息(称为 PEBS 记录)保存到一个特定的内存区域(PEBS 缓冲区),该缓冲区从 PEBS 基地址开始。它可以包含多条 PEBS 记录,PEBS 缓冲区内的尾部被称为 PEBS 索引。
PEBS 记录包含处理器的体系结构状态(通用寄存器、EIP 寄存器和 EFLAGS 寄存器的状态,目标地址和延迟信息(如果当前指令是加载),硬件交易(tx)中止 reason 标志(如果事件与 tx 有关),以及硬件时间戳)。PEBS 记录的格式在不同CPU上会不同。
只有PEBS 索引达到 PEBS 阈值时,才会触发一个硬件性能监控中断,告诉操作系统 PEBS 缓冲区几乎满了,请及时读取以便进一步处理。通过使用基于硬件的微代码保存上下文信息,PEBS 比普通的性能计数器有两个优势:
- 减少开销,PEBS 减少了中断的次数,操作系统仅在 PEBS 缓冲区填满时才参与,即在大量样本可用之前没有中断。例如,如果 PEBS 缓冲区在调用中断前能包含 100 条 PEBS 记录,那么与普通的性能计数器相比,中断次数就减少到 1/100。
- 计数器寄存器溢出的时间和保存上下文信息的时间之间的差距比基于中断的方法小得多,这使的与常规中断流程保存的指令指针相比,指令滑动被最小化。
尽管英特尔方面认为 PEBS 产生的开销可以忽略不计,但我们发现每次 PEBS 产生样本都会产生 200 纳秒的 CPU 开销,而且由于快速的PEBS记录写入,还会产生可预测的缓存污染。
4 在云上精准采样
上述的精准采样技术在裸金属上被 Linux 内核长期支持,但是这项技术在虚拟化软件栈中一直是缺位的。内核社区从2014年第一次尝试开始,发现了诸多软硬件技术难题需要解决。其中一个是,需要产生PEBS记录的CPU硬件能区分PEBS缓冲区地址是物理机的虚拟内存还是虚拟机的虚拟内存,避免缓冲区污染甚至信息泄漏,这部分难题需要硬件改动,由硬件厂商主导修复。同样在虚拟化软件栈中,除了向虚拟机呈现PEBS设备模型的编程接口外,如何让虚拟机动态申请并占用性能监控硬件单元,在物理机上安全可控的让虚拟机用户获得几乎一样的硬件性能事件探查能力,既要考虑到物理机上常驻的性能分析监控服务,又不能损害虚拟机用户的性能分析采样精度,都是一项项技术难题。
开源社区从来不缺少挑战者,腾讯云的内核开发者反复探索硬件厂商给出的PEBS修复方案,逐步摸清安全界限,积极搭建、重构与重写内核性能分析服务的虚拟化软件基础框架,一步步实现性能监控单元的各个特性,从Intel到AMD,逐步为开源KVM虚拟机使用PEBS精准性能采样技术铺平技术道路,成功帮助云上的开发者准确发现采样的性能事件以及导致它的程序指令。
在腾讯云的IaaS计算实例上,开发者已经可以通过开源的性能分析软件访问真实CPU的硬件性能反馈数据 (比如内存读写带宽、缓存使用率、分支预测成功率、指令解析与执行速度等),比如将数据包的 ID 存储到一个很少使用的通用寄存器中,并用 PEBS 对寄存器的值进行性能事件采样跟踪,成功识别出基于 DPDK 简单数据包转发器时有意外延迟的数据包及其链路,解决了网络延迟突发抖动分析难题。
包括Intel PEBS精准采样技术在内的腾讯云性能分析技术,可以进一步分析目标程序在一段时间内的运行状态及其真实资源需求,逐步量化目标软件被目标硬件实际执行时的硬件占有率与使用率,相较于此前由软件系统提供的软件性能指标,腾讯云的硬件性能事件虚拟化技术运行开销更低、性能数据更真实,此类技术已帮助云上开发者发现一个个性能瓶颈。
总结
Guest PEBS 技术方案的核心框架已经被上游社区接收,并被其他厂商广泛测试。作为另一块腾讯云上分析应用性能的底层软件基石,该技术进一步加固了腾讯云性能分析服务的技术领导力。腾讯云客户的业务开发者可基于真实量化的代码级硬件性能数据,深入了解自身业务的性能特征,追踪业务升级的性能变化,实现局部执行优化、热点延迟优化、响应长尾优化、全局调度优化,优化业务总体执行效率,降低业务总体计算成本。
值得一提的是,团队同时向io_uring 社区贡献多个特性与优化。通过单请求接受多次连接特性,提升短链接场景下的吞吐性能; 通过任务线程固定持久化,定向优化 io_uring 的线程机制,减少锁竞争开销。目前,uringlet 等多项异步IO优化技术,处于社区审查迭代阶段。