Perf笔记(二)

Perf_events所处理的hardware event(硬件事件)需要CPU的支持,而目前主流的CPU基本都包含了PMUPerformance Monitoring Unit,性能监控单元)。PMU用来统计性能相关的参数,像cache命中率,指令周期等等。由于这些统计工作是硬件完成的,所以CPU开销很小。

X86体系结构为例,PMU包含了两种MSRsModel-Specific Registers,之所以称之为Model-Specific,是因为不同modelCPU,有些register是不同的):Performance Event Select RegistersPerformance Monitoring CountersPMC)。当想对某种性能事件(performance event)进行统计时,需要对Performance Event Select Register进行设置,统计结果会存在Performance Monitoring Counter中。

perf_events工作在采样模式(samplingperf record命令即工作在这种模式)时,由于采样事件发生时和实际处理采样事件之间有时间上的delay,以及CPU流水线和乱序执行等因素,所以得到的指令地址IP(Instruction Pointer)并不是当时产生采样事件的IP,这个称之为skid。为了改善这种状况,使IP值更加准确,Intel使用PEBSPrecise Event-Based Sampling),而AMD则使用IBSInstruction-Based Sampling)。

PEBS为例:每次采样事件发生时,会先把采样数据存到一个缓冲区中(PEBS buffer),当缓冲区内容达到某一值时,再一次性处理,这样可以很好地解决skid问题。

执行一下perf list --help命令,会看到下面内容:

The p modifier can be used for specifying how precise the instruction address should be. The p modifier can be specified multiple times:

       0 - SAMPLE_IP can have arbitrary skid
       1 - SAMPLE_IP must have constant skid
       2 - SAMPLE_IP requested to have 0 skid
       3 - SAMPLE_IP must have 0 skid

For Intel systems precise event sampling is implemented with PEBS which supports up to precise-level 2.

现在可以理解,经常看到的类似“perf record -e "cpu/mem-loads/pp" -a”命令中,pp就是指定IP精度的。

闲侃CPU(一)

这个文章系列来自于Brendan Gregg所著《Systems Performance: Enterprise and the Cloud》一书第六章《CPU》的读书笔记。

系统板卡上的CPU插槽称之为socket,一颗物理CPU芯片可以称之为processor。现在CPU早已经进入多核时代,一颗CPU processor可以包含多个core,而一个core又可以包含多个hardware thread。每个hardware thread在操作系统看来,就是一个logic CPU,即一个可以被调度的CPU实例(instance)。举个例子,如果一颗CPU processor包含4core,而每个core又包含2hardware thread,则从操作系统角度看来,一共有8个可以使用的“CPU”(1*4*2 = 8)。

lscpu输出为例:

[root@linux ~]# lscpu
......
Architecture:          x86_64
CPU op-mode(s):        32-bit, 64-bit
Byte Order:            Little Endian
CPU(s):                120
On-line CPU(s) list:   0-119
Thread(s) per core:    2
Core(s) per socket:    15
Socket(s):             4
......

120 = 2 * 15 * 4, 即CPU(s) = Thread(s) per core * Core(s) per socket * Socket(s)

 

为了改善内存访问性能,CPU processor提供了寄存器3cache。整个存储模型如下所示(从上往下,容量越小,CPU访问越快):
* register(寄存器)
L1 cache
L2 cache
L3 cache
Main memory(主存储器)
Storage Device(外接存储器)

如何理解CPU利用率(译文)

以下这段文字翻译自技术大牛Brendan Gregg和Jim Mauro 2011年的著作:《DTrace: Dynamic Tracing in Oracle Solaris, Mac OS X and FreeBSD》第三章《System View》里关于CPU利用率的一个介绍(56页)。个人觉得写得很清晰,就把它翻译出来,希望能让更多人对CPU利用率有正确的理解。翻译有错之处,还希望大家批评指正。

在信息技术领域,CPU利用率作为一个重要能力度量指标已经有了很多年的历史了,它可以通过很多传统的“stat”工具得到(像Solaris的vmstat(1M)命令,等等)。随着处理器技术的演进,CPU利用率作为一个度量指标的实际意义和满意度正在减弱。拥有多个处理器的系统,拥有多核的处理器,拥有多个线程的处理器核,拥有多个执行单元(整数,浮点数)并允许多个线程并发地执行指令的处理器核等等这些因素,都会使我们对CPU利用率真正含义产生曲解,而不管CPU运行何种操作系统。

一个具体的例子是内存总线访问。当等待内存总线完成数据传输时,CPU的“装载”和“存储”指令也许会使CPU停下来。而这些停下来时耗费时钟周期发生在执行一条CPU指令期间,所以会被算作利用率,虽然可能和人们期待的不一样(虽然在使用却是在等待!)。

应用程序的并行化程度也是一个影响因素;一个单线程程序可以让一个CPU的利用率达到百分之百,却让其它CPU处于空闲状态。在一个拥有多个CPU的系统上,这种情况将使统计工具显示很低的系统级别的CPU利用率,而这很可能使你不会去深入了解CPU状态。一个充满竞争锁的多线程程序也许会使多个CPU的用率达到百分之百,而其中很多线程都在竞争锁,而不是真正地处理它们应该完成的任务。因此仅仅通过CPU利用率,并不足以让我们确定CPU本身是不是真正的性能问题。

清楚地了解CPU正在做什么(处理指令或是等待内存访问完成,正在执行用户应用程序还是操作系统内核程序)对我们将是很有益的。