如何测量linux中的实际CPU使用率?

时间:2015-01-26 14:23:12

标签: c linux gcc kernel profiling

我知道有一些工具,如顶部 ps 来衡量CPU使用率,但他们测量CPU使用率的方式是通过测量空闲任务的时间长短没跑因此,例如,即使CPU由于高速缓存未命中而导致停顿,这些工具仍将认为CPU被占用。但是,我想要的是分析工具在停顿期间将CPU视为空闲。是否有任何工具可以做到这一点?

1 个答案:

答案 0 :(得分:6)

  

用于测量CPU使用率的top和ps等工具,...测量CPU使用率是通过测量空闲任务未运行的时间。

不,他们没有测量空闲,他们只是通过/ proc / stat(也尝试vmstat 1工具)读取内核对其CPU使用率的看法。您是否检查过系统范围的用户+系统时间仅由idle计算?我认为,内核只会导出一些调度程序的统计信息,它会在重新安排时记录用户/系统状态,包括系统计时器和阻塞系统调用(可能是cpuacct_charge的一个调用者,如update_curr - 更新当前任务的运行时统计信息。)。

/ proc / stat示例:

cat /proc/stat
cpu  2255 34 2290 22625563 6290 127 456

并按http://www.linuxhowtos.org/System/procstat.htm

解码
  

第一个“cpu”行聚合所有其他“cpuN”行中的数字。这些数字表示CPU执行不同类型工作所花费的时间。时间单位为USER_HZ或 Jiffies (通常为百分之一秒)。

     

列的含义如下,从左到右:

user: normal processes executing in user mode
nice: niced processes executing in user mode
system: processes executing in kernel mode
idle: twiddling thumbs

当我们听到jiffie时,这意味着调度程序用于获取数字,而不是估计idle任务(顶部甚至看不到此任务或任务带有pid 0)。

  

因此,例如,即使CPU由于高速缓存未命中而导致停顿,这些工具仍会认为CPU被占用。

基本上(当没有SMT时,就像英特尔中的HT一样),当你的任务由于内存访问而导致管道停顿(或采用无序的错误路径)时,CPU就会被占用。操作系统无法运行其他任务,因为任务切换比等待这一档更加昂贵。

SMT的情况不同,因为有硬件可以在单个硬件上切换两个逻辑任务,甚至(在细粒度SMT中)将其指令(微操作)混合到单个流中以在共享硬件上执行。通常有SMT统计计数器来检查实际混合。

  

但是,我想要的是分析工具在停顿期间将CPU视为空闲。是否有任何工具可以做到这一点?

性能监控单元可能会为此提供有用的事件。例如,perf stat报告一些(在Sandy Bridge上)

$ perf stat /bin/sleep 10

 Performance counter stats for '/bin/sleep 10':
      0,563759 task-clock                #    0,000 CPUs utilized          
             1 context-switches          #    0,002 M/sec                  
             0 CPU-migrations            #    0,000 M/sec                  
           175 page-faults               #    0,310 M/sec                  
       888 767 cycles                    #    1,577 GHz                    
       568 603 stalled-cycles-frontend   #   63,98% frontend cycles idle   
       445 567 stalled-cycles-backend    #   50,13% backend  cycles idle   
       593 103 instructions              #    0,67  insns per cycle        
                                         #    0,96  stalled cycles per insn
       115 709 branches                  #  205,246 M/sec                  
         7 699 branch-misses             #    6,65% of all branches        

  10,000933734 seconds time elapsed

所以,它说睡眠10使用了0,5 jiffie(任务时钟)。它太低了,无法计入经典的rusage,并且/ usr / bin / time得到0 jiffie作为任务CPU使用率(用户+系统): $ / usr / bin / time sleep 10 0.00user 0.00system 0:10.00elapsed 0%CPU(0avgtext + 0avgdata 2608maxresident)k 0inputs + 0outputs(0major + 210minor)pagefaults 0swaps

然后执行测量(在PMU的帮助下计数)实际循环和由任务执行的实际指令(以及代表任务的内核) - cyclesinstructions行。睡眠已经使用了888k个周期,但只完成了593k个有用的指令,平均值IPC为0.6-0.7(30-40%的停顿)。失去了大约300k个周期;并在Sandy bridge perf上报告它们丢失的位置 - stalled-cycles-*前端事件(解码器 - CPU不知道由于分支未命中或由于未预取到L1I的代码而执行什么)以及后端(无法执行,因为指令需要来自内存的某些数据,这些数据在正确的时间不可用 - 内存停顿)。

为什么我们在没有执行任何指令的情况下应该只有300k个周期时看到CPU内部有更多停顿?这是因为现代处理器通常超标量且无序 - 它们可以在每个CPU时钟周期开始执行多个指令,甚至可以对它们进行重新排序。如果您想查看执行端口利用率,请尝试使用Andi Kleen的pmu-tools中的ocperf(perf wrapper)和一些有关其PMU计数器的英特尔手册。还有toplev.py脚本“识别工作负载的微架构瓶颈”,而无需手动选择英特尔事件。