内存CPU

内存CPU

六月 19, 2018

记线上服务因程序问题出现过内存泄露,导致服务器内存暴增,所以以此了解什么内存泄露

  • 内存泄漏(Memory Leak)是指程序中己动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。

  • 内存泄漏缺陷具有隐蔽性、积累性的特征,比其他内存非法访问错误更难检测。因为内存泄漏的产生原因是内存块未被释放,属于遗漏型缺陷而不是过错型缺陷。此外,内存泄漏通常不会直接产生可观察的错误症状,而是逐渐积累,降低系统整体性能,极端的情况下可能使系统崩溃。

image.png

###iowait
Percentage of time that the CPU or CPUs were idle during which the system had an outstanding disk I/O request
系统未完成的I/O请求占用的CPU百分比
%iowait 表示在一个采样周期内有百分之几的时间属于以下情况:CPU空闲、并且有仍未完成的I/O请求。
[root@ip]# sar -u
Linux 3.14.48-33.39.amzn1.x86_64 (ip) 10/18/2018 x86_64 (2 CPU)
12:00:01 AM CPU %user %nice %system %iowait %steal %idle
12:10:01 AM all 1.30 0.00 0.59 0.01 0.62 97.49
12:20:01 AM all 1.27 0.00 0.56 0.01 0.62 97.53
12:30:01 AM all 1.27 0.00 0.56 0.01 0.63 97.53
12:40:01 AM all 1.26 0.00 0.57 0.01 0.62 97.55
12:50:01 AM all 1.31 0.00 0.56 0.01 0.61 97.50
01:00:01 AM all 1.29 0.00 0.58 0.01 0.62 97.50
01:10:01 AM all 1.29 0.00 0.55 0.01 0.63 97.52
01:20:01 AM all 1.30 0.00 0.54 0.01 0.63 97.52
01:30:01 AM all 1.28 0.00 0.54 0.01 0.63 97.54
01:40:01 AM all 1.30 0.00 0.53 0.01 0.63 97.53
01:50:01 AM all 1.29 0.00 0.55 0.01 0.63 97.52
02:00:01 AM all 1.27 0.00 0.57 0.01 0.63 97.52
02:10:01 AM all 3.10 0.00 1.27 0.67 0.63 94.33
02:20:01 AM all 1.41 0.00 0.66 0.01 0.66 97.27
Average: all 1.43 0.00 0.62 0.06 0.63 97.27

1
2
3
4
误解  %iowait 升高并不能证明等待I/O的进程数量增多
在I/O完全一样的情况下,CPU忙闲状态的变化就能够影响 %iowait 的大小。在CPU繁忙期间发生的I/O,无论有多少,%iowait 的值都是不受影响的(因为 %iowait 的第一个前提条件就是CPU必须空闲);当CPU繁忙程度下降时,有一部分I/O落入了CPU空闲的时间段内,这就导致了 %iowait 升高。可见,I/O并没有变化,%iowait 却升高了,原因仅仅是CPU的空闲时间增加了。请记住,系统中有成百上千的进程数,任何一个进程都可以引起CPU和I/O的变化,因为 %iowait、%idle、%user、%system 等这些指标都是全局性的,并不是特指某个进程。
CPU的繁忙状况保持不变的条件下,即使 %iowait 升高也不能说明I/O负载加重了。如果2个I/O请求依次提交、使得整个时段内始终有I/O在进行,那么 %iowait 是100%;如果3个I/O请求同时提交,因为系统有能力同时处理多个I/O,所以3个并发的I/O从开始到结束的时间与一个I/O一样,%iowait 的结果只有50%2个I/O使 %iowait 达到了100%3个I/O的 %iowait 却只有50%,显然 %iowait 的高低与I/O的多少没有必然关系,而是与I/O的并发度相关。所以,仅凭 %iowait 的上升不能得出 I/O负载增加 的结论。
如果看到 %iowait 升高,还需检查I/O量有没有明显增加,avserv/avwait/avque等指标有没有明显增大,应用有没有感觉变慢,如果都没有,就没什么好担心的。

使用命令行 sar -u t n
每10秒采样一次,连续采样3次,观察CPU 的使用情况
[ec2-user@ip]$ sar -u 10 3
Linux 3.14.35-28.38.amzn1.x86_64 (ip) 10/18/2018 x86_64 (4 CPU)
03:51:52 AM CPU %user %nice %system %iowait %steal %idle
03:52:02 AM all 0.08 0.00 0.10 0.00 0.08 99.74
03:52:12 AM all 0.10 0.00 0.08 0.00 0.10 99.72
03:52:22 AM all 0.08 0.00 0.05 0.00 0.10 99.77
Average: all 0.09 0.00 0.08 0.00 0.09 99.74

  • %wio的值过高,表示硬盘存在I/O瓶颈,%idle值高,表示CPU较空闲,如果%idle值高但系统响应慢时,有可能是CPU等待分配内存,此时应加大内存容量。%idle值如果持续低于10,那么系统的CPU处理能力相对较低,表明系统中最需要解决的资源是CPU。
  • 在以上的显示当中,主要看%iowait和%idle,%iowait过高表示存在I/O瓶颈,即磁盘IO无法满足业务需求,如果%idle过低表示CPU使用率比较严重,需要结合内存使用等情况判断CPU是否瓶颈。

###iostat

1
2
是在Linux系统上查看I/O性能最基本的工具
在Linux上,每个I/O的平均耗时是用await表示的,但它不能反映硬盘设备的性能,因为await不仅包括硬盘设备处理I/O的时间,还包括了在队列中等待的时间。I/O请求在队列中的时候尚未发送给硬盘设备,即队列中的等待时间不是硬盘设备消耗的,所以说await体现不了硬盘设备的速度,内核的问题比如I/O调度器什么的也有可能导致await变大

[tai_ops@ip ~]$ iostat –help
Usage: iostat [ options ] [ [ ] ]
Options are:
[ -c ] [ -d ] [ -N ] [ -n ] [ -h ] [ -k | -m ] [ -t ] [ -V ] [ -x ] [ -y ] [ -z ]
[ -j { ID | LABEL | PATH | UUID | … } [ […] | ALL ] ]
[ […] | ALL ] [ -p [ [,…] | ALL ] ]
命令参数:
-C 显示CPU使用情况
-d 显示磁盘使用情况
-k 以 KB 为单位显示
-m 以 M 为单位显示
-N 显示磁盘阵列(LVM) 信息
-n 显示NFS 使用情况
-p[磁盘] 显示磁盘和分区的情况
-t 显示终端和CPU的信息
-x 显示详细信息
-V 显示版本信息

常用方法:
iostat -d -k 1 10 #查看TPS和吞吐量信息
iostat -d -x -k 1 10 #查看设备使用率(%util)、响应时间(await)
iostat -c 1 10 #查看cpu状态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
案例分析:
[ec2-user@ip ~]$ iostat -d -k 2 5
Linux 3.14.48-33.39.amzn1.x86_64 (ip) 08/14/2017 _x86_64_ (4 CPU)

Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn
xvda 0.15 0.03 0.87 107088 3435228

Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn
xvda 1.00 0.00 4.00 0 8

Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn
xvda 0.50 0.00 2.00 0 4

Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn
xvda 0.00 0.00 0.00 0 0

Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn
xvda 0.00 0.00 0.00 0 0
分析:
输出结果一KB为单位,每2秒收集一次信息,一共收集5次,xvda每秒传输次数为0.15,每秒读磁盘0.03KB,写磁盘0.87KB,取样读磁盘总数107088KB,写磁盘总数为3435228KB

[ec2-user@ip ~]$ iostat -d -x -k 3 5
Linux 3.14.48-33.39.amzn1.x86_64 (ip) 08/14/2017 _x86_64_ (4 CPU)

Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await svctm %util
xvda 0.00 0.06 0.00 0.15 0.03 0.87 12.04 0.00 0.38 0.28 0.00

Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await svctm %util
xvda 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00

Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await svctm %util
xvda 0.00 0.67 0.00 0.67 0.00 5.33 16.00 0.00 0.00 0.00 0.00

Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await svctm %util
xvda 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00

Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await svctm %util
xvda 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00

分析:
输出结果以KB为单位,每3秒收集一次,一共收集5次,每秒向磁盘上写5KB左右数据(wkB/s值),每秒约有1次IO操作(r/s+w/s),其中以写操作为主体,平均每次IO请求等待处理的时间为0.38毫秒,处理耗时为0.28 毫秒,等待处理的IO请求队列中,平均有0个请求驻留


[ec2-user@ip ~]$ iostat -c 3 5
Linux 3.14.48-33.39.amzn1.x86_64 (ip) 08/14/2017 _x86_64_ (4 CPU)

avg-cpu: %user %nice %system %iowait %steal %idle
3.96 0.00 1.21 0.00 0.11 94.71

avg-cpu: %user %nice %system %iowait %steal %idle
4.06 0.00 1.27 0.00 0.08 94.59

avg-cpu: %user %nice %system %iowait %steal %idle
3.65 0.00 1.19 0.00 0.17 95.00

avg-cpu: %user %nice %system %iowait %steal %idle
4.06 0.00 1.10 0.00 0.17 94.67

avg-cpu: %user %nice %system %iowait %steal %idle
3.81 0.00 1.10 0.00 0.08 95.00

分析:
用户CPU利用率约4%,优先级CPU利用率为0,系统CPU利用率约1.2%,IO挂起空闲百分比为0,虚拟CPU百分比约0.17,IO没有挂起空闲百分比约95%
单独使用
[ec2-user@ip ~]$ iostat
Linux 3.14.48-33.39.amzn1.x86_64 (ip) 08/14/2017 _x86_64_ (4 CPU)

avg-cpu: %user %nice %system %iowait %steal %idle
3.96 0.00 1.21 0.00 0.11 94.71

Device: tps Blk_read/s Blk_wrtn/s Blk_read Blk_wrtn
xvda 0.15 0.05 1.75 214177 6868520

单独执行iostat,显示的结果为从系统开机到当前执行时刻的统计信息


案例分析:
用户CPU利用率为3.96%,优先级用户CPU利用率为0,系统CPU利用率为1.21%,IO挂起空闲时间百分比为0,虚拟CPU时间百分比为0.11%,IO没有挂起空闲时间百分比为94.71,xvda每秒传输次数为0.15,每秒读磁盘0.05,写磁盘1.75,取样读磁盘总数为214177,写总数为6868520

最上面指示系统版本、主机名和日期

avg-cpu: 总体cpu使用情况统计信息,对于多核cpu,这里为所有cpu的平均值

  • %user : 显示了在执行用户(应用)层时的CPU利用率
  • %nice : 显示了在以nice优先级运行用户层的CPU利用率
  • %system : 显示了在执行系统(内核)层时的CPU利用率
  • %iowait : 显示了CPU在I/O请求挂起时空闲时间的百分比
  • %steal : 显示了当hypervisor正服务于另外一个虚拟处理器时无意识地等待虚拟CPU所占有的时间百分比。
  • %idle : 显示了CPU在I/O没有挂起请求时空闲时间的百分比

Device: 各磁盘设备的IO统计信息

  • Device: 设备名称
  • tps: 设备每秒的传输次数(Indicate the number of transfers per second that were issued to the device.)。“一次传输”意思是“一次I/O请求”。多个逻辑请求可能会被合并为“一次I/O请求”。“一次传输”请求的大小是未知的。
  • Blk_read/s: 每秒读扇区数量(一扇区为512bytes)
  • Blk_wrtn/s: 每秒写扇区数量
  • Blk_read: 取样时间间隔内读扇区总数量
  • Blk_wrtn: 取样时间间隔内写扇区总数量

如果%iowait的值过高,表示硬盘存在I/O瓶颈,%idle值高,表示CPU较空闲,如果%idle值高但系统响应慢时,有可能是CPU等待分配内存,此时应加大内存容量。%idle值如果持续低于10,那么系统的CPU处理能力相对较低,表明系统中最需要解决的资源是CPU。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
指定采样时间间隔与采样次数
指定iostat命令的采样间隔和采样次数:每2秒采集一次,一共采集3
[ec2-user@ip ~]$ iostat -d 2 3
Linux 3.14.48-33.39.amzn1.x86_64 (ip) 08/14/2017 _x86_64_ (4 CPU)

Device: tps Blk_read/s Blk_wrtn/s Blk_read Blk_wrtn
xvda 0.15 0.05 1.75 214177 6869944

Device: tps Blk_read/s Blk_wrtn/s Blk_read Blk_wrtn
xvda 0.00 0.00 0.00 0 0

Device: tps Blk_read/s Blk_wrtn/s Blk_read Blk_wrtn
xvda 0.00 0.00 0.00 0 0

案例分析:
xvda每秒传输次数为0.15,每秒读磁盘为0.05,写磁盘为1.75,取样读磁盘总数为214177,写磁盘为6869944


以kB为单位显示读写信息(-k选项)
使用-k选项,指定iostat的部分输出结果以kB为单位,而不是以扇区数为单位:

[tai_ops@ip ~]$ iostat -d -k
Linux 3.14.48-33.39.amzn1.x86_64 (ip) 08/14/2017 _x86_64_ (8 CPU)

Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn
xvda 55.11 0.08 6979.67 149976 13936026432

以上输出中,kB_read/s、kB_wrtn/s、kB_read和kB_wrtn的值均以kB为单位,相比以扇区数为单位,这里的值为原值的一半(1kB=512bytes*2)

(-m选项)以M为单位
[tai_ops@ip ~]$ iostat -m
Linux 3.14.48-33.39.amzn1.x86_64 (ip) 08/14/2017 _x86_64_ (8 CPU)

avg-cpu: %user %nice %system %iowait %steal %idle
1.75 0.00 0.19 0.86 0.08 97.13

Device: tps MB_read/s MB_wrtn/s MB_read MB_wrtn
xvda 55.06 0.00 6.81 146 13609407

更详细的io统计信息(-x选项)
为显示更详细的io设备统计信息,我们可以使用-x选项,在分析io瓶颈时,一般都会开启-x选项:

[tai_ops@ip ~]$ iostat -d -k -x 3 3
Linux 3.14.48-33.39.amzn1.x86_64 (ip) 08/14/2017 _x86_64_ (8 CPU)

Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await svctm %util
xvda 0.00 0.85 0.01 55.10 0.08 6978.66 253.30 1.02 18.52 0.94 5.20

Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await svctm %util
xvda 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00

Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await svctm %util
xvda 0.00 2.00 0.00 1.00 0.00 13.33 26.67 0.00 0.00 0.00 0.00
  • rrqm/s: 每秒对该设备的读请求被合并次数,文件系统会对读取同块(block)的请求进行合并
  • wrqm/s: 每秒对该设备的写请求被合并次数
  • r/s: 每秒完成的读次数
  • w/s: 每秒完成的写次数
  • rkB/s: 每秒读数据量(kB为单位)
  • wkB/s: 每秒写数据量(kB为单位)
  • avgrq-sz:平均每次IO操作的数据量(扇区数为单位)
  • avgqu-sz: 平均等待处理的IO请求队列长度
  • await: 平均每次IO请求等待时间(包括等待时间和处理时间,毫秒为单位)
  • svctm: 平均每次IO请求的处理时间(毫秒为单位)
  • %util: 采用周期内用于IO操作的时间比率,即IO队列非空的时间比率

对于以上示例输出,我们可以获取到以下信息:

  • 每秒向磁盘上写7M左右数据(wkB/s值)
  • (r/s+w/s),其中以写操作为主体
  • 平均每次IO请求等待处理的时间为18.52毫秒,处理耗时为0.94 毫秒
  • 等待处理的IO请求队列中,平均有1.02个请求驻留

util = (r/s+w/s) * (svctm/1000)

如果 %util 接近 100%,说明产生的I/O请求太多,I/O系统已经满负荷,该磁盘可能存在瓶颈。如果 svctm 比较接近 await,说明 I/O 几乎没有等待时间;如果 await 远大于 svctm,说明I/O 队列太长,io响应太慢,则需要进行必要优化。如果avgqu-sz比较大,也表示有大量io在等待。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

获取cpu部分状态值 (-c选项)

[tai_ops@ip ~]$ iostat -c 2 3
Linux 3.14.48-33.39.amzn1.x86_64 (ip) 08/14/2017 _x86_64_ (8 CPU)

avg-cpu: %user %nice %system %iowait %steal %idle
1.75 0.00 0.19 0.86 0.08 97.13

avg-cpu: %user %nice %system %iowait %steal %idle
0.00 0.00 0.00 0.00 0.00 100.00

avg-cpu: %user %nice %system %iowait %steal %idle
0.00 0.00 0.00 0.00 0.00 100.00


显示tty和Cpu信息 (-t选项)
[tai_ops@ip ~]$ iostat -t
Linux 3.14.48-33.39.amzn1.x86_64 (ip) 08/14/2017 _x86_64_ (8 CPU)

08/14/2017 09:19:28 AM
avg-cpu: %user %nice %system %iowait %steal %idle
1.75 0.00 0.19 0.86 0.08 97.13

Device: tps Blk_read/s Blk_wrtn/s Blk_read Blk_wrtn
xvda 55.05 0.15 13944.15 299952 27872069752

iostat [ -c | -d ] [ -k ] [ -t ] [ -V ] [ -x [ device ] ] [ interval [ count ] ]

-x,该选项将用于显示和io相关的扩展数据
其中,-c为汇报CPU的使用情况;-d为汇报磁盘的使用情况;-k表示每秒按kilobytes字节显示数据;-t为打印汇报的时间;-v表示打印出版本信息和用法;-x device指定要统计的设备名称,默认为所有的设备;interval指每次统计间隔的时间;count指按照这个时间间隔统计的次数。

%util: 一秒中有百分之多少的时间用于 I/O 操作,或者说一秒中有多少时间 I/O 队列是非空的。即 delta(use)/s/1000 (因为use的单位为毫秒)

await:每一个IO请求的处理的平均时间(单位是毫秒)。这里可以理解为IO的响应时间,一般地系统IO响应时间应该低于5ms,如果大于10ms就比较大了。

%util:在统计时间内所有处理IO时间,除以总共统计时间。例如,如果统计间隔1秒,该设备有0.8秒在处理IO,而0.2秒闲置,那么该设备的%util = 0.8/1 = 80%,所以该参数暗示了设备的繁忙程度。一般地,如果该参数是100%表示设备已经接近满负荷运行了(当然如果是多磁盘,即使%util是100%,因为磁盘的并发能力,所以磁盘使用未必就到了瓶颈)。

1
2
3
iostat -d -k 1 10    查看TPS和吞吐量信息

iostat -d -x -k 1 10 #查看设备使用率(%util)、响应时间(await)