分析Memory使用状况
内存是影响服务器性能的一个主要因素, 当进程已经驻留内存或者系能够分配给进程足够的内存给它, CPU能顺利自如的运行. 如果发生内存不足, 服务器使用I/O channel获取数据, 由于访问I/O channel速度大约比访问内存满1000倍, 这会给服务器带了性能问题.
Page大小
操作系统以内存页管理内存, 页大小会对系统系统性能有影响. 在i386系统中, 页大小默认为4KB, 对于系统经常处理大量小文件, 这是没有问题的. 但是如果系统经常处理大文件, 页大小为4KB会使服务器性能低效, 这种情况下页大小为2M更好. 当系统使用完内存后, 这是系统会使用swap memory, 由于swap memory是一种模拟memory的硬盘, 而不是真正的内存, 所以当系统使用swap memory时, 系统会非常慢. 所以当系统速度很慢时, 首先查看swap memory使用状况, swap memory的使用情况可以通过free -m查看.
1.
[root@rdhl ~]
# free -m
2.
total used
free
shared buffers cached
3.
Mem: 3832 2715 1116 0 43 37
4.
-/+ buffers/cache: 2635 1197
5.
Swap: 3967 0 3967
如果发现系统在使用swap, 接下来做的就是需要通过vmstat -s查看使用swap的具体情况, 如果使用swap很多, 那么系统速度会很慢, 因此需要考虑增加内存或者移除使用内存很多的进程.
Active和Inactive内存
在Linux内核决定哪些内存页需要交换(swap)时, 系统根据Active memory和Inactive memory来判断. 所谓Active memory就是最近被使用的内存, Inactive memory是已经有一段时间没有被使用的内存. 当内核需要从RMA到swap移动内存块时, 内核会确保只有Inactive memory的内存块会被移到. 系统的Active memory和Inactive memory可以通过vmstat -s查看.
01.
[root@rdhl ~]
# vmstat -s
02.
3924700 total memory
03.
2781632 used memory
04.
39228 active memory
05.
63784 inactive memory
06.
1143068
free
memory
07.
44644 buffer memory
08.
38348 swap cache
09.
4063224 total swap
10.
0 used swap
11.
4063224
free
swap
12.
9091 non-
nice
user cpu ticks
13.
76
nice
user cpu ticks
14.
1849895 system cpu ticks
15.
23999960 idle cpu ticks
16.
110671 IO-wait cpu ticks
17.
0 IRQ cpu ticks
18.
228 softirq cpu ticks
19.
0 stolen cpu ticks
20.
84027541 pages paged
in
21.
358313 pages paged out
22.
0 pages swapped
in
23.
0 pages swapped out
24.
21388189 interrupts
25.
2499501 CPU context switches
26.
1395818922 boot
time
27.
7884 forks
从上面可以看出Active memory相对Inactive memory要小.
内核内存
当分析内存使用状况时, 内核本身使用的内存也需要考虑, 这种内存叫做slab memory, 可以通过/pro/meminfo来查看.
01.
[root@rdhl ~]
# cat /proc/meminfo
02.
MemTotal: 3924700 kB
03.
MemFree: 1142084 kB
04.
Buffers: 45476 kB
05.
Cached: 38372 kB
06.
SwapCached: 0 kB
07.
Active: 39284 kB
08.
Inactive: 64612 kB
09.
Active(anon): 10336 kB
10.
Inactive(anon): 9880 kB
11.
Active(
file
): 28948 kB
12.
Inactive(
file
): 54732 kB
13.
Unevictable: 0 kB
14.
Mlocked: 0 kB
15.
SwapTotal: 4063224 kB
16.
SwapFree: 4063224 kB
17.
Dirty: 4 kB
18.
Writeback: 0 kB
19.
AnonPages: 20048 kB
20.
Mapped: 8748 kB
21.
Shmem: 168 kB
22.
Slab: 78396 kB
23.
SReclaimable: 24932 kB
24.
SUnreclaim: 53464 kB
25.
KernelStack: 920 kB
26.
PageTables: 3176 kB
27.
NFS_Unstable: 0 kB
28.
Bounce: 0 kB
29.
WritebackTmp: 0 kB
30.
CommitLimit: 6025572 kB
31.
Committed_AS: 118392 kB
32.
VmallocTotal: 34359738367 kB
33.
VmallocUsed: 281896 kB
34.
VmallocChunk: 34359454008 kB
35.
HardwareCorrupted: 0 kB
36.
AnonHugePages: 2048 kB
37.
HugePages_Total: 0
38.
HugePages_Free: 0
39.
HugePages_Rsvd: 0
40.
HugePages_Surp: 0
41.
Hugepagesize: 2048 kB
42.
DirectMap4k: 10240 kB
43.
DirectMap2M: 4184064 kB
从上可以看到内核使用slab memory的大小, 如果需要查看更加详细的内核使用内存信息, 可以使用slabtop命令.
01.
[root@rdhl ~]
# slabtop
02.
Active / Total Objects (% used) : 1037851 / 1042500 (99.6%)
03.
Active / Total Slabs (% used) : 16568 / 16568 (100.0%)
04.
Active / Total Caches (% used) : 99 / 185 (53.5%)
05.
Active / Total Size (% used) : 66243.50K / 66845.72K (99.1%)
06.
Minimum / Average / Maximum Object : 0.02K / 0.06K / 4096.00K
07.
OBJS ACTIVE USE OBJ SIZE SLABS OBJ/SLAB CACHE SIZE NAME
08.
550224 550216 99% 0.02K 3821 144 15284K avtab_node
09.
353696 353524 99% 0.03K 3158 112 12632K size-32
10.
25360 25266 99% 0.19K 1268 20 5072K dentry
11.
20617 20498 99% 0.07K 389 53 1556K selinux_inode_security
12.
17228 16974 98% 0.06K 292 59 1168K size-64
13.
13528 13525 99% 0.99K 3382 4 13528K ext4_inode_cache
14.
12469 12455 99% 0.10K 337 37 1348K buffer_head
15.
9477 9453 99% 0.14K 351 27 1404K sysfs_dir_cache
16.
5778 5772 99% 0.58K 963 6 3852K inode_cache
17.
4028 3977 98% 0.07K 76 53 304K Acpi-Operand
18.
3960 3948 99% 0.12K 132 30 528K size-128
19.
2852 2808 98% 0.04K 31 92 124K Acpi-Namespace
20.
2489 2451 98% 0.20K 131 19 524K vm_area_struct
21.
2233 1931 86% 0.05K 29 77 116K anon_vma_chain
22.
2160 2115 97% 0.19K 108 20 432K size-192
23.
1656 1408 85% 0.04K 18 92 72K anon_vma
24.
1357 511 37% 0.06K 23 59 92K avc_node
25.
1302 1288 98% 0.55K 186 7 744K radix_tree_node
26.
940 806 85% 0.19K 47 20 188K filp
27.
920 772 83% 0.04K 10 92 40K dm_io
28.
915 854 93% 0.25K 61 15 244K size-256
29.
864 772 89% 0.02K 6 144 24K dm_target_io
30.
784 768 97% 0.50K 98 8 392K size-512
31.
752 734 97% 1.00K 188 4 752K size-1024
32.
744 743 99% 2.00K 372 2 1488K size-2048
33.
645 577 89% 0.25K 43 15 172K skbuff_head_cache
34.
640 636 99% 0.77K 128 5 512K shmem_inode_cache
35.
384 384 100% 0.64K 64 6 256K proc_inode_cache
36.
380 236 62% 0.19K 19 20 76K cred_jar
37.
280 273 97% 0.53K 40 7 160K idr_layer_cache
38.
235 235 100% 4.00K 235 1 940K size-4096
39.
202 6 2% 0.02K 1 202 4K jbd2_revoke_table
40.
184 184 100% 32.12K 184 1 11776K kmem_cache
对于内存性能分析, 系统管理员最感兴趣的是slab使用内存大小和NAME和SIZE, 如果slab使用的内存很高, 也许这个模块发生了什么错误, 也可能需要更新内核信息.
使用ps分析内存
使用ps来调整内存使用情况的优势是ps给出服务器上所有进程的内存使用大小. 通常使用ps aux来查看内存使用情况, 其中特别需要关注VSZ和RSS, VSZ(Virtual Size)是指virtual memory使用情况, 这是进程申请的总的内存大小, RSS(Resident Size)是指进程实际使用的内存大小.
01.
[root@rdhl ~]
# ps aux | more
02.
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
03.
root 1 0.0 0.0 19356 1432 ? Ss Mar26 0:01 /sbin/init
04.
root 2 0.0 0.0 0 0 ? S Mar26 0:00 [kthreadd]
05.
root 3 0.0 0.0 0 0 ? S Mar26 0:00 [migration/0]
06.
root 4 0.0 0.0 0 0 ? S Mar26 0:00 [ksoftirqd/0]
07.
root 5 0.0 0.0 0 0 ? S Mar26 0:00 [migration/0]
08.
root 6 0.0 0.0 0 0 ? S Mar26 0:00 [watchdog/0]
09.
root 7 0.0 0.0 0 0 ? S Mar26 0:00 [migration/1]
10.
root 8 0.0 0.0 0 0 ? S Mar26 0:00 [migration/1]
11.
root 9 0.0 0.0 0 0 ? S Mar26 0:00 [ksoftirqd/1]
12.
root 10 0.0 0.0 0 0 ? S Mar26 0:00 [watchdog/1]
13.
root 11 0.0 0.0 0 0 ? S Mar26 0:07 [events/0]
14.
root 12 0.0 0.0 0 0 ? S Mar26 0:08 [events/1]
15.
root 13 0.0 0.0 0 0 ? S Mar26 0:00 [cgroup]
16.
root 14 0.0 0.0 0 0 ? S Mar26 0:00 [khelper]
17.
root 15 0.0 0.0 0 0 ? S Mar26 0:00 [netns]
18.
root 16 0.0 0.0 0 0 ? S Mar26 0:00 [async/mgr]
19.
root 17 0.0 0.0 0 0 ? S Mar26 0:00 [pm]
20.
root 18 0.0 0.0 0 0 ? S Mar26 0:00 [sync_supers]
21.
root 19 0.0 0.0 0 0 ? S Mar26 0:00 [bdi-default]
从上面的输出可以发现有些进程用[]括起来, 而另外一些没有, 用[]括起来的进程是内核的一部分, 其他的是正常的进程.
有两种方法可以详细了解一个进程到底在做什么, 其中一种是到/proc下找到指定进程ID, 进入该目录找到maps文件, 该文件给出了内存怎么映射到这个进程, 比如进程使用的内存地址, 子程序和库.
01.
7f990a7bc000-7f990a7c8000 r-xp 00000000 fd:00 2359326 /lib64/libnss_files-2.12.so
02.
7f990a7c8000-7f990a9c8000 ---p 0000c000 fd:00 2359326 /lib64/libnss_files-2.12.so
03.
7f990a9c8000-7f990a9c9000 r--p 0000c000 fd:00 2359326 /lib64/libnss_files-2.12.so
04.
7f990a9c9000-7f990a9ca000 rw-p 0000d000 fd:00 2359326 /lib64/libnss_files-2.12.so
05.
7f990a9ca000-7f990a9d1000 r-xp 00000000 fd:00 2359722 /lib64/librt-2.12.so
06.
7f990a9d1000-7f990abd0000 ---p 00007000 fd:00 2359722 /lib64/librt-2.12.so
07.
7f990abd0000-7f990abd1000 r--p 00006000 fd:00 2359722 /lib64/librt-2.12.so
08.
7f990abd1000-7f990abd2000 rw-p 00007000 fd:00 2359722 /lib64/librt-2.12.so
09.
7f990abd2000-7f990ac0b000 r-xp 00000000 fd:00 2359738 /lib64/libnspr4.so
10.
7f990ac0b000-7f990ae0a000 ---p 00039000 fd:00 2359738 /lib64/libnspr4.so
11.
7f990ae0a000-7f990ae0b000 r--p 00038000 fd:00 2359738 /lib64/libnspr4.so
12.
7f990ae0b000-7f990ae0d000 rw-p 00039000 fd:00 2359738 /lib64/libnspr4.so
13.
7f990ae0d000-7f990ae0f000 rw-p 00000000 00:00 0
14.
7f990ae0f000-7f990ae12000 r-xp 00000000 fd:00 2359740 /lib64/libplds4.so
15.
7f990ae12000-7f990b011000 ---p 00003000 fd:00 2359740 /lib64/libplds4.so
16.
7f990b011000-7f990b012000 r--p 00002000 fd:00 2359740 /lib64/libplds4.so
17.
7f990b012000-7f990b013000 rw-p 00003000 fd:00 2359740 /lib64/libplds4.so
另一种方法是使用pmap -d PID, 如:
01.
[root@rdhl proc]
# pmap -d 8290
02.
8290:
dd
if
=/dev/urandom of=/dev/null
03.
Address Kbytes Mode Offset Device Mapping
04.
0000000000400000 48 r-x-- 0000000000000000 0fd:00000
dd
05.
000000000060b000 8 rw--- 000000000000b000 0fd:00000
dd
06.
0000000001aa4000 132 rw--- 0000000000000000 000:00000 [ anon ]
07.
000000305a600000 128 r-x-- 0000000000000000 0fd:00000 ld-2.12.so
08.
000000305a81f000 4 r---- 000000000001f000 0fd:00000 ld-2.12.so
09.
000000305a820000 4 rw--- 0000000000020000 0fd:00000 ld-2.12.so
10.
000000305a821000 4 rw--- 0000000000000000 000:00000 [ anon ]
11.
000000305ae00000 1576 r-x-- 0000000000000000 0fd:00000 libc-2.12.so
12.
000000305af8a000 2048 ----- 000000000018a000 0fd:00000 libc-2.12.so
13.
000000305b18a000 16 r---- 000000000018a000 0fd:00000 libc-2.12.so
14.
000000305b18e000 4 rw--- 000000000018e000 0fd:00000 libc-2.12.so
15.
000000305b18f000 20 rw--- 0000000000000000 000:00000 [ anon ]
16.
000000305b200000 92 r-x-- 0000000000000000 0fd:00000 libpthread-2.12.so
17.
000000305b217000 2048 ----- 0000000000017000 0fd:00000 libpthread-2.12.so
18.
000000305b417000 4 r---- 0000000000017000 0fd:00000 libpthread-2.12.so
19.
000000305b418000 4 rw--- 0000000000018000 0fd:00000 libpthread-2.12.so
20.
000000305b419000 16 rw--- 0000000000000000 000:00000 [ anon ]
21.
000000305b600000 28 r-x-- 0000000000000000 0fd:00000 librt-2.12.so
22.
000000305b607000 2044 ----- 0000000000007000 0fd:00000 librt-2.12.so
23.
000000305b806000 4 r---- 0000000000006000 0fd:00000 librt-2.12.so
24.
000000305b807000 4 rw--- 0000000000007000 0fd:00000 librt-2.12.so
25.
00007fd95653b000 96836 r---- 0000000000000000 0fd:00000 locale-archive
26.
00007fd95c3cc000 12 rw--- 0000000000000000 000:00000 [ anon ]
27.
00007fd95c3d9000 4 rw--- 0000000000000000 000:00000 [ anon ]
28.
00007ffffe83e000 84 rw--- 0000000000000000 000:00000 [ stack ]
29.
00007ffffe988000 4 r-x-- 0000000000000000 000:00000 [ anon ]
30.
ffffffffff600000 4 r-x-- 0000000000000000 000:00000 [ anon ]
31.
mapped: 105180K writeable/private: 296K shared: 0K
使用pmap的优势是pmap给出一个进程工作时详细顺序信息, 通过这个命令能看到进程调用外部库和以[anon]结束表示通过malloc进行内存分配请求.
ory使用状况