zoukankan      html  css  js  c++  java
  • CPU性能分析工具原理

    转载请保留以下声明
      作者:赵宗晟
      出处:https://www.cnblogs.com/zhao-zongsheng/p/13067733.html

    很多软件都要做性能分析和性能优化。很多语言都会有他的性能分析工具,例如如果优化C++的性能,我们可以用Visual Studio自带的性能探测器,或者使用Intel VTune Profiler。了解性能分析工具的原理有助于了解工具给出的数据与结果,也能帮助我们在遇到异常结果时排查哪里出了问题。这篇博客简单总结一下常见的性能分析工具原理。

    性能分析器原理分类

    性能分析工具大部分都可以分为下面几类

    1. 基于采样(Sampling)
    2. 基于插装(Instrumentation)
    3. 基于事件(Event-based)

    1. 基于采样

    基于采样的分析器会每隔一个固定时间间隔暂停所有线程的执行,然后分析有哪些线程正在执行,那些线程处于就绪状态。对于这类线程,我们记录每个线程的调用堆栈,以及其他需要的信息。我们称这个行为为一次采样,记录下来的每个堆栈为一个样本。然后在结束性能分析的时候我们统计记录下载的堆栈,看每个堆栈被记录了多少次,或者每个函数被记录了多少次。统计学告诉我们,那些执行时间比较长的函数、堆栈,被记录的次数会更多。如果堆栈A被记录了200次,堆栈B被记录了100次,那么堆栈B的执行时间是堆栈A的2倍。我们可以计算某个堆栈样本的数量占总样本数的比例,这个比例就是堆栈执行时间的占比。用Visual Studio的性能探测器我们看到的百分比和数字就是值样本的占比(也就是时间占比)和样本次数。

    很多性能分析工具都是基于采样的方式。运行性能分析器是会影响被测程序的性能的,而基于采样的有点是对性能影响比较小,不需要重新编译程序,非常方便。

    2.基于插装

    插装是指通过修改程序,往里面加入性能分析相关代码,来收集、监控相关性能指标。例如我们可以在一个函数的开头写下计数代码,我们就可以知道在运行中这个函数被执行了多少次。一般来说基于插装的性能分析更为准确,但是对性能影响比较大。因为需要修改代码,所以也不是很方便。另外,基于插装的分析也可能会引起海森堡bug(heisenbug)。海森堡bug是指当你再运行程序的时候能遇到这个bug,但是试图定位这个bug时却遇不到这个bug。这个bug往往是因为在定位bug时修改了软件的运行环境/流程,导致软件执行和生产时不一样,于是就遇不到这个bug了。这个命名的来源很有意思,海森堡是量子力学的著名科学家,他提出了不确定性原理,以及观察者理论。这个理论认为,观察会影响例子的状态,导致观察粒子和不观察粒子会导致不同的结果,这个和海森堡bug的情形非常相似。关于观察者理论,有兴趣的人可以再了解一下。

    回到正题,基于插装也可以再进行划分:

    • 人手修改源码:这个是我们非常常用的性能分析方法。我们做性能分析有时候就会直接修改源码,计算某一段代码的执行时长,或者计算函数调用次数,分析哪段代码耗时。
    • 工具自动修改源码
    • 工具自动修改汇编/中间码
    • 运行时注入
    • ......

    3.基于事件

    在软件执行过程中,可能会抛出某些事件。我们通过统计事件出现的次数,事件出现的时机,可以得到软件的某些性能指标。事件又可以分为软件事件和硬件事件。软件事件比如Java可以在class-load的时候抛出事件。硬件事件则是使用专门的性能分析硬件。现在很多CPU里面都有用于分析性能的性能监控单元(PMU),PMU本身是一个寄存器,在某个事件发生时寄存器里面的值会+1。例如我们可以设置为当运行中发生memory cache miss的时候PMU寄存器+1,这样我们就知道一段时间内发生了多少次memory cache miss。性能分析器使用PMU时,会给PMU设置需要统计的事件类型,以及Sample After Value (SAV)。SAV是指寄存器达到什么值之后出发硬件中断。例如,我们可以给PMU设置SAV为2000,统计事件为memory cache miss。那么当cache miss发生2000次时,发生硬件中断。这个时候性能分析器就可以收集CPU的IP,调用堆栈,进程ID等等信息,分析器结束时进行统计分析。

    基于硬件事件的优点是,对被测程序的影响非常小,比基于采样还小,可以使用更短的时间间隔收集信息,而且可以收集CPU的非常重要的性能指标,例如cache miss,分支预测错误,等等。

    但是基于硬件事件的分析器也有它的一些问题,导致数据上的误差:

    • SAV一般会设置成很大的数值:
      像是Intel VTune Profiler一般会把SAV设置成10,000到2,000,000,发生中断时我们能知道最后一次触发该事件是哪段代码引起的,但是在这之前的9,999到1,999,999次事件我们是不知道的。他会认为所有10,000到2,000,000次事件都是由同一处代码引起的。如果发生了很多次中断,收集了很多次信息,而某一行代码出现了很多次,那么根据统计学,我们能知道这行代码触发了多少次事件。但是如果某一行代码只出现了一两次,那么我们很难知道这行代码到底出发了多少次时间。
    • CPU一个核只有几个PMU,但是可以统计的事件有几十种:
      一个PMU可以统计一个事件,但是我们分析一个软件可能需要统计几十种事件。一般的处理方法是多路复用(Multiplexing)。比如说前10ms记录事件A,后10ms记录事件B,再后10ms由记录事件A,……,这样轮流记录事件A和事件B,那么一个PMU就可以同时统计两个事件。多路复用可以解决少量PMU统计大量事件的问题,但是也会导致每种事件记录的样本数减少,倒是最后统计计算的结果误差更大。
    • Intel® Hyper-Threading Technology导致记录不准:
      Hyper-Threading技术可以让一个CPU物理核变成两个逻辑核,但是这两个逻辑核会共享很多硬件,包括PMU。这会出现什么问题呢?例如我们有两个线程再两个CPU核同时运行。我们觉得实在两个核上执行,但是实际上是在同一个物理核上。所以PMU会同时统计两个程序触发的事件,我们很难区分到底是哪个逻辑核出发了多少事件,所以PMU记录的数据就会不准确。另外,性能分析器计算性能指标时会使用一些硬件参数,Hyper-Threading技术会让这些参数不准确。例如一般个CPU核能再一个clock执行4个uop,所以CPI(Cycle Per Instruction,每个clock执行的指令数)是0.25。但是如果使用了Hyper-Threading技术,实际的CPI会是0.5
    • Event Skid(事件打滑)会导致记录的IP不准确:
      PMU记录有些事件会出现一定延时,所以在执行分析器的中断处理代码时,可能被测程序已经又执行了好多指令,IP已经向后滑动了很远了。一般如果我们只是统计函数的话不会太大问题,但是我们想统计指令时就会有很大问题了。比如我们可能会看到某个add指令导致了大量的分支预测错误,显然这个是不可能的。往往这种时候我们可以看看前面一点的指令。
    • Interrupt Masking(中断屏蔽),导致统计出来的空闲状态比正常的高
      不同的中断有不同的优先级,为了高优先级的中断处理程序不被打断,我们可以选择屏蔽一部分中断事件。但是PMU的事件也是一个中断,如果系统中有大量的中断屏蔽,那么会有PMU的中断被屏蔽掉一部分,导致统计出来的数据不准确。表现出来的效果就是,统计出来的处于空闲状态的时间比实际的要高。

    总结

    这几个就是比较常见的性能分析方法。我们知道了性能分析的原理,可以更好地理解性能分析器给出的结果,也可以在出现明显异常的结果时,分析判断可能的原因,针对性的解决。

    参考

    https://en.wikipedia.org/wiki/Profiling_(computer_programming)
    https://software.intel.com/content/www/us/en/develop/articles/understanding-how-general-exploration-works-in-intel-vtune-amplifier-xe.html
    https://software.intel.com/content/www/us/en/develop/documentation/vtune-help/top/analyze-performance/user-mode-sampling-and-tracing-collection.html
    https://software.intel.com/content/www/us/en/develop/documentation/vtune-help/top/analyze-performance/hardware-event-based-sampling-collection.html

  • 相关阅读:
    Single Number II
    Pascal's Triangle
    Remove Duplicates from Sorted Array
    Populating Next Right Pointers in Each Node
    Minimum Depth of Binary Tree
    Unique Paths
    Sort Colors
    Swap Nodes in Pairs
    Merge Two Sorted Lists
    Climbing Stairs
  • 原文地址:https://www.cnblogs.com/zhao-zongsheng/p/13067733.html
Copyright © 2011-2022 走看看