像top和ps这样的工具用于测量CPU使用率,..通过测量空闲任务没有运行的时间来测量CPU使用率。
不,他们不测量空闲,他们只是通过 /proc/stat 读取内核对其 CPU 使用情况的看法(尝试vmstat 1
工具也)。您是否检查过系统范围的用户+系统时间仅由idle
?我认为,内核只是导出调度程序的一些统计信息,它记录重新调度时的用户/系统状态,包括系统计时器和阻塞系统调用(可能是调用者之一)cpuacct_charge http://lxr.free-electrons.com/ident?v=3.16;i=cpuacct_charge, like update_curr
- 更新当前任务的运行时统计信息。).
/proc/stat 示例:
cat /proc/stat
cpu 2255 34 2290 22625563 6290 127 456
并解码为http://www.linuxhowtos.org/System/procstat.htm 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 https://en.wikipedia.org/wiki/Simultaneous_multithreading与 Intel 中的 HT 类似),当您的任务由于内存访问(或无序而采取错误路径)而导致管道停顿时,CPU 就会被占用。操作系统无法运行其他任务,因为任务切换比等待这一任务的成本更高。
SMT 的情况有所不同,因为有些硬件要么在单个硬件上切换两个逻辑任务,要么甚至(在细粒度 SMT 中)将它们的指令(微操作)混合到单个流中以在共享硬件上执行。通常有SMT统计计数器来检查实际的混合情况。
然而,我想要的是分析工具在停顿期间将 CPU 视为空闲状态。有没有什么工具可以做到这一点?
性能监控单元可能有对此有用的事件。例如,perf stat
报道了一些(在桑迪布里奇)
$ 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
因此,它表示 sleep 10 使用了 0,5 jiffie(任务时钟)。它太低,无法在经典 rusage 中计算,并且 /usr/bin/time 得到 0 jiffie 作为任务 CPU 使用率(用户 + 系统) ):
$ /usr/bin/时间睡眠 10
0.00user 0.00system 0:10.00elapsed 0%CPU (0avgtext+0avgdata 2608maxresident)k
0 个输入+0 个输出(0 个主要+210 个次要)页面错误 0 个交换
然后 perf 测量(在 PMU 的帮助下计数)任务执行的实际周期和实际指令(以及代表任务的内核) -cycles
and instructions
线。 Sleep 使用了 888k 个周期,但只完成了 593k 条有用指令,这意味着IPC https://en.wikipedia.org/wiki/Instructions_per_cycle为 0.6-0.7(30-40% 失速)。大约丢失了 30 万个周期;和桑迪桥上perf
报告他们失踪的地点 -stalled-cycles-*
前端事件(解码器 - 由于分支未命中或代码未预取到 L1I,CPU 不知道要执行什么)和后端事件(无法执行,因为指令需要内存中的一些数据,而这些数据在正确的时间不可用 -内存停滞)。
为什么我们在 CPU 内部看到更多的停顿,而实际上应该只有 300k 个周期而没有执行任何指令?这是因为现代处理器通常是超标量和无序的 - 它们可以在每个 CPU 时钟周期开始执行多个指令,甚至重新排序它们。如果您想查看执行端口利用率,请尝试ocperf
(性能包装)来自 Andi Kleen'spmu工具 https://github.com/andikleen/pmu-tools以及一些有关 PMU 计数器的 Intel 手册。还有toplev.py
脚本为“识别工作负载的微架构瓶颈“无需手动选择英特尔事件。