CPU性能分析工具原理
很多软件都要做性能分析和性能优化。很多语言都会有他的性能分析工具,例如如果优化C++的性能,我们可以用Visual Studio自带的性能探测器,或者使用Intel VTune Profiler。了解性能分析工具的原理有助于了解工具给出的数据与结果,也能帮助我们在遇到异常结果时排查哪里出了问题。这篇博客简单总结一下常见的性能分析工具原理。
性能分析器原理分类
性能分析工具大部分都可以分为下面几类
- 基于采样(Sampling)
- 基于插装(Instrumentation)
- 基于事件(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
CPU性能分析工具原理的更多相关文章
- Linux性能优化:CPU性能分析工具--vmstat
Blog:博客园 个人 目录 参数说明 输出信息说明 procs memory swap io system cpu 示例 vmstat是Virtual Meomory Statistics(虚拟内存 ...
- CPU性能分析
CPU性能分析工具 lscpu:查看CPU硬件信息 lscpu Architecture: x86_64 CPU op-mode(s): 32-bit, 64-bit Byte Order: Litt ...
- Linux下性能分析工具汇总
来自:http://os.51cto.com/art/201104/253114.htm 本文讲述的是:CPU性能分析工具.Memory性能分析工具.I/O性能分析工具.Network性能分析工具. ...
- 系统级性能分析工具 — Perf
从2.6.31内核开始,linux内核自带了一个性能分析工具perf,能够进行函数级与指令级的热点查找. perf Performance analysis tools for Linux. Perf ...
- Linux性能分析工具与图形化方法
欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~. 作者:赵坤|腾讯魔王工作室后台开发工程师 在项目开发中,经常会遇到程序启动时间过长.CPU使用率过高等问题,这个时候需要依靠性能分析工具来 ...
- 系统级性能分析工具perf的介绍与使用[转]
测试环境:Ubuntu16.04(在VMWare虚拟机使用perf top存在无法显示问题) Kernel:3.13.0-32 系统级性能优化通常包括两个阶段:性能剖析(performance pro ...
- Linux 性能分析工具汇总合集
出于对Linux操作系统的兴趣,以及对底层知识的强烈欲望,因此整理了这篇文章.本文也可以作为检验基础知识的指标,另外文章涵盖了一个系统的方方面面.如果没有完善的计算机系统知识,网络知识和操作系统知识, ...
- [转]Linux性能分析工具汇总合集
出于对Linux操作系统的兴趣,以及对底层知识的强烈欲望,因此整理了这篇文章.本文也可以作为检验基础知识的指标,另外文章涵盖了一个系统的方方面面.如果没有完善的计算机系统知识,网络知识和操作系统知识, ...
- 超全整理!Linux性能分析工具汇总合集
转自:http://rdc.hundsun.com/portal/article/731.html?ref=myread 出于对Linux操作系统的兴趣,以及对底层知识的强烈欲望,因此整理了这篇文章. ...
随机推荐
- Havel定理 poj1659
http://blog.csdn.net/xcszbdnl/article/details/14174669 代码风格这里的 Frogs' Neighborhood Time Limit: 5000M ...
- CF948B Primal Sport
题目链接:http://codeforces.com/contest/948/problem/B 知识点: 素数 解题思路: \(f(x)\) 表示 \(x\) 的最大素因子.不难想到:\(X_1 \ ...
- 【Redis】Set常见应用场景
微信抽奖小程序 >点击参与抽奖加入集合 SADD key {userID} >查看参与抽奖所有用户 SMEMBERS key >抽取count名中奖者 SRANGEMEMBER ke ...
- Java-第15章图形用户界面设计例题
Example15_1.java JFrame常用方法 import javax.swing.*; import static javax.swing.JFrame.*; public class E ...
- multipart_formdata
import requests def sendImg(img_path, img_name, img_type='image/jpeg'): """ :param im ...
- 集合框架之ArrayList -Java
ArrayList 1.与数组的区别 如果要存放多个对象,可以使用数组,但是数组会有长度的限制,会出现不够用或者是浪费的情况. 为了解决数组的局限性引入了容器的概念,最常用的容器就是ArrayList ...
- Win10下安装Linux子系统-Ubuntu
工作以来一直DotNet系偏C/S, 接触Web开发的时间也不长, 现在主要偏向Web全栈方向, 一直对Linux系统心生向往, 夜深了娃睡了, 打开老旧的笔记本来折腾一下. 准备工作 控制面板 &g ...
- 利用Nginx设置跨域的方式
1.服务端可控,添加响应头 2.服务端不可控.通过Nginx反向代理 3.服务端不可控.通过Nginx反向代理添加响应头 第一种方法.服务端可控时,可以在服务器端添加响应头(前端+后端解决) 浏览器地 ...
- 重学 Java 设计模式:实战适配器模式
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 擦屁屁纸80%的面积都是保护手的! 工作到3年左右很大一部分程序员都想提升自己的技术 ...
- c#tcp多线程服务器实例代码
using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using Sy ...