1. 程式人生 > 其它 >Linux效能優化和監控系列(三)——分析Memory使用狀況

Linux效能優化和監控系列(三)——分析Memory使用狀況

分析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檢視.

[root@rdhl ~]# free -m

total used free shared buffers cached

Mem: 3832 2715 1116 0 43 37

-/+ buffers/cache: 2635 1197

Swap: 3967 0 3967


如果發現系統在使用swap, 接下來做的就是需要通過vmstat -s檢視使用swap的具體情況, 如果使用swap很多, 那麼系統速度會很慢, 因此需要考慮增加記憶體或者移除使用記憶體很多的程序.


ActiveInactive記憶體

在Linux核心決定哪些記憶體頁需要交換(swap)時, 系統根據Active memoryInactive memory來判斷. 所謂Active memory就是最近被使用的記憶體, Inactive memory是已經有一段時間沒有被使用的記憶體. 當核心需要從RMA到swap移動記憶體塊時, 核心會確保只有Inactive memory的記憶體塊會被移到. 系統的Active memory

Inactive memory可以通過vmstat -s檢視.

[root@rdhl ~]# vmstat -s

3924700 total memory

2781632 used memory

39228 active memory

63784 inactive memory

1143068 free memory

44644 buffer memory

38348 swap cache

4063224 total swap

0 used swap

4063224 free swap

9091 non-nice user cpu ticks

76 nice user cpu ticks

1849895 system cpu ticks

23999960 idle cpu ticks

110671 IO-wait cpu ticks

0 IRQ cpu ticks

228 softirq cpu ticks

0 stolen cpu ticks

84027541 pages paged in

358313 pages paged out

0 pages swapped in

0 pages swapped out

21388189 interrupts

2499501 CPU context switches

1395818922 boot time

7884 forks

從上面可以看出Active memory相對Inactive memory要小.


核心記憶體

當分析記憶體使用狀況時, 核心本身使用的記憶體也需要考慮, 這種記憶體叫做slab memory, 可以通過/pro/meminfo來檢視.

[root@rdhl ~]# cat /proc/meminfo

MemTotal: 3924700 kB

MemFree: 1142084 kB

Buffers: 45476 kB

Cached: 38372 kB

SwapCached: 0 kB

Active: 39284 kB

Inactive: 64612 kB

Active(anon): 10336 kB

Inactive(anon): 9880 kB

Active(file): 28948 kB

Inactive(file): 54732 kB

Unevictable: 0 kB

Mlocked: 0 kB

SwapTotal: 4063224 kB

SwapFree: 4063224 kB

Dirty: 4 kB

Writeback: 0 kB

AnonPages: 20048 kB

Mapped: 8748 kB

Shmem: 168 kB

Slab: 78396 kB

SReclaimable: 24932 kB

SUnreclaim: 53464 kB

KernelStack: 920 kB

PageTables: 3176 kB

NFS_Unstable: 0 kB

Bounce: 0 kB

WritebackTmp: 0 kB

CommitLimit: 6025572 kB

Committed_AS: 118392 kB

VmallocTotal: 34359738367 kB

VmallocUsed: 281896 kB

VmallocChunk: 34359454008 kB

HardwareCorrupted: 0 kB

AnonHugePages: 2048 kB

HugePages_Total: 0

HugePages_Free: 0

HugePages_Rsvd: 0

HugePages_Surp: 0

Hugepagesize: 2048 kB

DirectMap4k: 10240 kB

DirectMap2M: 4184064 kB

從上可以看到核心使用slab memory的大小, 如果需要檢視更加詳細的核心使用記憶體資訊, 可以使用slabtop命令.

[root@rdhl ~]# slabtop

Active / Total Objects (% used) : 1037851 / 1042500 (99.6%)

Active / Total Slabs (% used) : 16568 / 16568 (100.0%)

Active / Total Caches (% used) : 99 / 185 (53.5%)

Active / Total Size (% used) : 66243.50K / 66845.72K (99.1%)

Minimum / Average / Maximum Object : 0.02K / 0.06K / 4096.00K

OBJS ACTIVE USE OBJ SIZE SLABS OBJ/SLAB CACHE SIZE NAME

550224 550216 99% 0.02K 3821 144 15284K avtab_node

353696 353524 99% 0.03K 3158 112 12632K size-32

25360 25266 99% 0.19K 1268 20 5072K dentry

20617 20498 99% 0.07K 389 53 1556K selinux_inode_security

17228 16974 98% 0.06K 292 59 1168K size-64

13528 13525 99% 0.99K 3382 4 13528K ext4_inode_cache

12469 12455 99% 0.10K 337 37 1348K buffer_head

9477 9453 99% 0.14K 351 27 1404K sysfs_dir_cache

5778 5772 99% 0.58K 963 6 3852K inode_cache

4028 3977 98% 0.07K 76 53 304K Acpi-Operand

3960 3948 99% 0.12K 132 30 528K size-128

2852 2808 98% 0.04K 31 92 124K Acpi-Namespace

2489 2451 98% 0.20K 131 19 524K vm_area_struct

2233 1931 86% 0.05K 29 77 116K anon_vma_chain

2160 2115 97% 0.19K 108 20 432K size-192

1656 1408 85% 0.04K 18 92 72K anon_vma

1357 511 37% 0.06K 23 59 92K avc_node

1302 1288 98% 0.55K 186 7 744K radix_tree_node

940 806 85% 0.19K 47 20 188K filp

920 772 83% 0.04K 10 92 40K dm_io

915 854 93% 0.25K 61 15 244K size-256

864 772 89% 0.02K 6 144 24K dm_target_io

784 768 97% 0.50K 98 8 392K size-512

752 734 97% 1.00K 188 4 752K size-1024

744 743 99% 2.00K 372 2 1488K size-2048

645 577 89% 0.25K 43 15 172K skbuff_head_cache

640 636 99% 0.77K 128 5 512K shmem_inode_cache

384 384 100% 0.64K 64 6 256K proc_inode_cache

380 236 62% 0.19K 19 20 76K cred_jar

280 273 97% 0.53K 40 7 160K idr_layer_cache

235 235 100% 4.00K 235 1 940K size-4096

202 6 2% 0.02K 1 202 4K jbd2_revoke_table

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)是指程序實際使用的記憶體大小.

[root@rdhl ~]# ps aux | more

USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND

root 1 0.0 0.0 19356 1432 ? Ss Mar26 0:01 /sbin/init

root 2 0.0 0.0 0 0 ? S Mar26 0:00 [kthreadd]

root 3 0.0 0.0 0 0 ? S Mar26 0:00 [migration/0]

root 4 0.0 0.0 0 0 ? S Mar26 0:00 [ksoftirqd/0]

root 5 0.0 0.0 0 0 ? S Mar26 0:00 [migration/0]

root 6 0.0 0.0 0 0 ? S Mar26 0:00 [watchdog/0]

root 7 0.0 0.0 0 0 ? S Mar26 0:00 [migration/1]

root 8 0.0 0.0 0 0 ? S Mar26 0:00 [migration/1]

root 9 0.0 0.0 0 0 ? S Mar26 0:00 [ksoftirqd/1]

root 10 0.0 0.0 0 0 ? S Mar26 0:00 [watchdog/1]

root 11 0.0 0.0 0 0 ? S Mar26 0:07 [events/0]

root 12 0.0 0.0 0 0 ? S Mar26 0:08 [events/1]

root 13 0.0 0.0 0 0 ? S Mar26 0:00 [cgroup]

root 14 0.0 0.0 0 0 ? S Mar26 0:00 [khelper]

root 15 0.0 0.0 0 0 ? S Mar26 0:00 [netns]

root 16 0.0 0.0 0 0 ? S Mar26 0:00 [async/mgr]

root 17 0.0 0.0 0 0 ? S Mar26 0:00 [pm]

root 18 0.0 0.0 0 0 ? S Mar26 0:00 [sync_supers]

root 19 0.0 0.0 0 0 ? S Mar26 0:00 [bdi-default]

從上面的輸出可以發現有些程序用[]括起來, 而另外一些沒有, 用[]括起來的程序是核心的一部分, 其他的是正常的程序.


有兩種方法可以詳細瞭解一個程序到底在做什麼, 其中一種是到/proc下找到指定程序ID, 進入該目錄找到maps檔案, 該檔案給出了記憶體怎麼對映到這個程序, 比如程序使用的記憶體地址, 子程式和庫.

7f990a7bc000-7f990a7c8000 r-xp 00000000 fd:00 2359326 /lib64/libnss_files-2.12.so

7f990a7c8000-7f990a9c8000 ---p 0000c000 fd:00 2359326 /lib64/libnss_files-2.12.so

7f990a9c8000-7f990a9c9000 r--p 0000c000 fd:00 2359326 /lib64/libnss_files-2.12.so

7f990a9c9000-7f990a9ca000 rw-p 0000d000 fd:00 2359326 /lib64/libnss_files-2.12.so

7f990a9ca000-7f990a9d1000 r-xp 00000000 fd:00 2359722 /lib64/librt-2.12.so

7f990a9d1000-7f990abd0000 ---p 00007000 fd:00 2359722 /lib64/librt-2.12.so

7f990abd0000-7f990abd1000 r--p 00006000 fd:00 2359722 /lib64/librt-2.12.so

7f990abd1000-7f990abd2000 rw-p 00007000 fd:00 2359722 /lib64/librt-2.12.so

7f990abd2000-7f990ac0b000 r-xp 00000000 fd:00 2359738 /lib64/libnspr4.so

7f990ac0b000-7f990ae0a000 ---p 00039000 fd:00 2359738 /lib64/libnspr4.so

7f990ae0a000-7f990ae0b000 r--p 00038000 fd:00 2359738 /lib64/libnspr4.so

7f990ae0b000-7f990ae0d000 rw-p 00039000 fd:00 2359738 /lib64/libnspr4.so

7f990ae0d000-7f990ae0f000 rw-p 00000000 00:00 0

7f990ae0f000-7f990ae12000 r-xp 00000000 fd:00 2359740 /lib64/libplds4.so

7f990ae12000-7f990b011000 ---p 00003000 fd:00 2359740 /lib64/libplds4.so

7f990b011000-7f990b012000 r--p 00002000 fd:00 2359740 /lib64/libplds4.so

7f990b012000-7f990b013000 rw-p 00003000 fd:00 2359740 /lib64/libplds4.so


另一種方法是使用pmap -d PID, 如:

[root@rdhl proc]# pmap -d 8290

8290: dd if=/dev/urandom of=/dev/null

Address Kbytes Mode Offset Device Mapping

0000000000400000 48 r-x-- 0000000000000000 0fd:00000 dd

000000000060b000 8 rw--- 000000000000b000 0fd:00000 dd

0000000001aa4000 132 rw--- 0000000000000000 000:00000 [ anon ]

000000305a600000 128 r-x-- 0000000000000000 0fd:00000 ld-2.12.so

000000305a81f000 4 r---- 000000000001f000 0fd:00000 ld-2.12.so

000000305a820000 4 rw--- 0000000000020000 0fd:00000 ld-2.12.so

000000305a821000 4 rw--- 0000000000000000 000:00000 [ anon ]

000000305ae00000 1576 r-x-- 0000000000000000 0fd:00000 libc-2.12.so

000000305af8a000 2048 ----- 000000000018a000 0fd:00000 libc-2.12.so

000000305b18a000 16 r---- 000000000018a000 0fd:00000 libc-2.12.so

000000305b18e000 4 rw--- 000000000018e000 0fd:00000 libc-2.12.so

000000305b18f000 20 rw--- 0000000000000000 000:00000 [ anon ]

000000305b200000 92 r-x-- 0000000000000000 0fd:00000 libpthread-2.12.so

000000305b217000 2048 ----- 0000000000017000 0fd:00000 libpthread-2.12.so

000000305b417000 4 r---- 0000000000017000 0fd:00000 libpthread-2.12.so

000000305b418000 4 rw--- 0000000000018000 0fd:00000 libpthread-2.12.so

000000305b419000 16 rw--- 0000000000000000 000:00000 [ anon ]

000000305b600000 28 r-x-- 0000000000000000 0fd:00000 librt-2.12.so

000000305b607000 2044 ----- 0000000000007000 0fd:00000 librt-2.12.so

000000305b806000 4 r---- 0000000000006000 0fd:00000 librt-2.12.so

000000305b807000 4 rw--- 0000000000007000 0fd:00000 librt-2.12.so

00007fd95653b000 96836 r---- 0000000000000000 0fd:00000 locale-archive

00007fd95c3cc000 12 rw--- 0000000000000000 000:00000 [ anon ]

00007fd95c3d9000 4 rw--- 0000000000000000 000:00000 [ anon ]

00007ffffe83e000 84 rw--- 0000000000000000 000:00000 [ stack ]

00007ffffe988000 4 r-x-- 0000000000000000 000:00000 [ anon ]

ffffffffff600000 4 r-x-- 0000000000000000 000:00000 [ anon ]

mapped: 105180K writeable/private: 296K shared: 0K

使用pmap的優勢是pmap給出一個程序工作時詳細順序資訊, 通過這個命令能看到程序呼叫外部庫和以[anon]結束表示通過malloc進行記憶體分配請求.