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很多, 那麼系統速度會很慢, 因此需要考慮增加內存或者移除使用內存很多的進程.


Active和Inactive內存

在Linux內核決定哪些內存頁需要交換(swap)時, 系統根據Active memoryInactive memory來判斷. 所謂Active memory就是最近被使用的內存, Inactive memory是已經有一段時間沒有被使用的內存. 當內核需要從RMA到swap移動內存塊時, 內核會確保只有Inactive memory的內存塊會被移到. 系統的Active memoryInactive 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進行內存分配請求.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章