分析CPU性能
top命令提供了监控CPU性能的基本功能, 如果需要更加深入的挖掘CPU的性能问题, top所提供的信息不足以做到. 由于大多数人认为CPU性能是体现服务器性能的主要因素, 所以在遇到性能问题时, 通常会首先查看CPU的性能来分析服务器的性能问题. 但事实上, 很多情况不是这样的,性能问题可能是由跟CPU相关的其他因素引起的, 比如CPU等待I/O资源.对于下面两个task:
Task 1:
1.
dd
if
=/dev/urandom of=/dev/null
Task 2:
1.
#!/bin/bash
2.
COUNTER=0
3.
while
true
4.
do
5.
dd
if
=/dev/urandom of=/root/
file
.$COUNTER bs=1M count=1
6.
COUNTER=$(( COUNTER + 1 ))
7.
[ COUNTER = 1000 ] &&
exit
8.
done
执行Task 1和Task 2后, sy都会增高, 但是执行Task 2时, wa也会增高, 这说明Task 1和Task 2都会使sy增高, 但是Task 2有时需要等待I/O资源, 所以wa也会增高.
理解CPU性能
为了监控CPU到底在做什么, 需要深入理解Linux内核是怎样工作的, 其中一个重要的组件是运行时队列(run queue), 每个CPU核有一个运行时队列, 在CPU为进程提供服务时, 进程需要首先进入运行时队列等待CPU分配CPU时间. 运行队列里包括可运行的进程(runnable process)和被阻挡的进程(blocked process). Linux的scheduler根据进程的优先级决定哪个runnable process运行, blocked process不会竞争CPU时间. top命令的load arverage是所有runnable process和blocked process的负载的总体概述. 如果需要查看哪些进程处于runnable和blocked状态, 可以通过vmstat来查看, 如:
1.
[root@rdhl ~]
# vmstat
2.
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----
3.
r b swpd
free
buff cache si so bi bo
in
cs us sy
id
wa st
4.
1 0 0 3747904 15492 27980 0 0 767 3 28 17 0 1 98 1 0
上下文切换和中断
在多任务操作系统中, Linux内核不断在不同进程之间进行上下文切换, 这种上下文切换需要CPU保存旧进程的上下文信息以及检索上下文信息给新进程, 因此上下文切换对CPU的性能代价是很高的. 减少上下文切换带来的性能问题最好的方法是减少上下文切换的次数, 在多核CPU架构中可以实现, 但是需要确保进程被锁定在指定CPU核上来阻止上下文切换. Linux进程调度器并不是进程发生上下文切换的唯一原因, 另一个导致上下文切换发生的原因是硬件中断(hardware interrupts). 进程调度器使用时钟中断(timer interrupt)保证每个进程能获取公平的CPU时间. 正常情况下上下文切换的次数应该小于时钟中断的次数, 如果发现上下文切换次数比时钟中断次数多, 这种负载可能是由系统需要处理很多I/O或者长时间高强度系统调用引起. 因此了解时钟中断和上下文切换的关系对找到引起系统性能问题的原因提供线索. 使用vmstat -s可以查看系统上下文切换和时钟中断次数, 这对查看高数量的上下文切换和IOWAIT的组合非常有帮助, 通过这可以判定系统试着做大量的写操作, 但是不能. 如下是vmstat -s的输出例子:
01.
[root@rdhl ~]
# vmstat -s
02.
3924700 total memory
03.
218964 used memory
04.
32152 active memory
05.
43332 inactive memory
06.
3705736
free
memory
07.
22400 buffer memory
08.
31492 swap cache
09.
4063224 total swap
10.
0 used swap
11.
4063224
free
swap
12.
7643 non-
nice
user cpu ticks
13.
0
nice
user cpu ticks
14.
1390112 system cpu ticks
15.
15353492 idle cpu ticks
16.
110105 IO-wait cpu ticks
17.
0 IRQ cpu ticks
18.
185 softirq cpu ticks
19.
0 stolen cpu ticks
20.
84007231 pages paged
in
21.
333713 pages paged out
22.
0 pages swapped
in
23.
0 pages swapped out
24.
16203245 interrupts
25.
2121904 CPU context switches
26.
1395818922 boot
time
27.
5780 forks
另一个查看CPU性能的指标是中断数, 中断数可以从/proc/interrupts查看,/pro/interrupts包含每种类型的中断被处理的次数. 如果中断数很高, 那表示Linux内核花很多时间处理中断而导致只有少部分时间处理其他进程.
01.
[root@rdhl ~]
# cat /proc/interrupts
02.
CPU0 CPU1
03.
0: 142 0 IO-APIC-edge timer
04.
1: 7 1 IO-APIC-edge i8042
05.
3: 1 0 IO-APIC-edge
06.
4: 1 0 IO-APIC-edge
07.
7: 0 0 IO-APIC-edge parport0
08.
8: 0 0 IO-APIC-edge rtc0
09.
9: 0 0 IO-APIC-fasteoi acpi
10.
12: 108 2 IO-APIC-edge i8042
11.
14: 0 0 IO-APIC-edge ata_piix
12.
15: 107 1 IO-APIC-edge ata_piix
13.
24: 0 0 PCI-MSI-edge pciehp
14.
25: 0 0 PCI-MSI-edge pciehp
15.
26: 0 0 PCI-MSI-edge pciehp
16.
27: 0 0 PCI-MSI-edge pciehp
17.
28: 0 0 PCI-MSI-edge pciehp
18.
29: 0 0 PCI-MSI-edge pciehp
19.
30: 0 0 PCI-MSI-edge pciehp
20.
31: 0 0 PCI-MSI-edge pciehp
21.
32: 0 0 PCI-MSI-edge pciehp
22.
33: 0 0 PCI-MSI-edge pciehp
23.
34: 0 0 PCI-MSI-edge pciehp
24.
35: 0 0 PCI-MSI-edge pciehp
25.
36: 0 0 PCI-MSI-edge pciehp
26.
37: 0 0 PCI-MSI-edge pciehp
27.
38: 0 0 PCI-MSI-edge pciehp
28.
39: 0 0 PCI-MSI-edge pciehp
29.
40: 0 0 PCI-MSI-edge pciehp
30.
41: 0 0 PCI-MSI-edge pciehp
31.
42: 0 0 PCI-MSI-edge pciehp
32.
43: 0 0 PCI-MSI-edge pciehp
33.
44: 0 0 PCI-MSI-edge pciehp
34.
45: 0 0 PCI-MSI-edge pciehp
35.
46: 0 0 PCI-MSI-edge pciehp
36.
47: 0 0 PCI-MSI-edge pciehp
37.
48: 0 0 PCI-MSI-edge pciehp
38.
49: 0 0 PCI-MSI-edge pciehp
39.
50: 0 0 PCI-MSI-edge pciehp
40.
51: 0 0 PCI-MSI-edge pciehp
41.
52: 0 0 PCI-MSI-edge pciehp
42.
53: 0 0 PCI-MSI-edge pciehp
43.
54: 0 0 PCI-MSI-edge pciehp
44.
55: 0 0 PCI-MSI-edge pciehp
45.
56: 1468 667997 PCI-MSI-edge vmw_pvscsi
46.
57: 367182 0 PCI-MSI-edge eth0-rxtx-0
47.
58: 13 115039 PCI-MSI-edge eth0-rxtx-1
48.
59: 0 0 PCI-MSI-edge eth0-event-2
49.
NMI: 0 0 Non-maskable interrupts
50.
LOC: 13249018 2561591 Local timer interrupts
51.
SPU: 0 0 Spurious interrupts
52.
PMI: 0 0 Performance monitoring interrupts
53.
IWI: 0 0 IRQ work interrupts
54.
RES: 35986 18866 Rescheduling interrupts
55.
CAL: 298172 228 Function call interrupts
56.
TLB: 1052 2847 TLB shootdowns
57.
TRM: 0 0 Thermal event interrupts
58.
THR: 0 0 Threshold APIC interrupts
59.
MCE: 0 0 Machine check exceptions
60.
MCP: 285 285 Machine check polls
61.
ERR: 0
62.
MIS: 0
使用vmstat
虽然top能监控CPU的大部分信息, 但是不能提供更加详细的CPU信息, 而vmstat可以堪当此任. vmstat有两种使用方式, 一种是sample mode, 在这种方式中, vmstat每个一段时间获取当前系统信息, 如每隔3秒执行一次, vmstat 3. 另一种是加-s选项, 在这种方式中, vmstat获取从系统启动后的系统统计信息, 除了CPU信息, 也包含memory, I/O, swap等.
cs | 上下文切换次数. |
us | CPU花在用户空间的时间百分比. |
sy | CPU花在系统空间的时间百分比. |
id | CPU空闲百分比. |
wa | CPU等待I/O的时间百分比. |