Linux程式記憶體佔用數的計算

denglt發表於2013-06-19
 前幾天同事反饋:資料庫主機上的server process佔用的實體記憶體過大,比v$process檢視中的大很多。他是使用ps檢視rss來計算實體記憶體的。
 
 man ps中對rss的解釋:
  RSS      resident set size, the non-swapped physical memory that a task has used (in kiloBytes).
                    (alias rssize, rsz).
 通過這個解釋,大家很容易認為RSS就是process實際佔用的實體記憶體。
 
其實,ps命令出來的rss結果是不正確的。因為ps在計算RSS時是包括了共享記憶體的。這個共享記憶體是多個process間共享的,實際上僅是佔用了一份記憶體。
 
讓我們通過實驗來證明:
實驗環境:Oracle Linux6.2(虛擬機器)
oracle版本:
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
PL/SQL Release 11.2.0.1.0 - Production
CORE    11.2.0.1.0      Production
TNS for Linux: Version 11.2.0.1.0 - Production
NLSRTL Version 11.2.0.1.0 - Production
 
[root@study1 ~]# ps aux | head -1;ps aux | grep 22922
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
oracle   22922  0.2  1.9 462176 28820 ?        Ss   09:20   0:00 oraclestudydb1 (DESCRIPTION=(LOCAL=YES)(ADDRESS=(PROTOCOL=beq)))
root     22955  0.0  0.0   4328   728 pts/1    S+   09:21   0:00 grep 22922
 
22922 為sqlplus連線資料庫產生的服務端oracle process,這裡RSS=28820k(28多m)
使用pmap分析程式22922
[root@study1 ~]# pmap -d 22922
22922:   oraclestudydb1 (DESCRIPTION=(LOCAL=YES)(ADDRESS=(PROTOCOL=beq)))
Address   Kbytes Mode  Offset           Device    Mapping
08048000  136740 r-x-- 0000000000000000 0fd:00000 oracle
105d1000    1004 rwx-- 0000000008589000 0fd:00000 oracle
106cc000     200 rwx-- 0000000000000000 000:00000   [ anon ]
1169b000     400 rwx-- 0000000000000000 000:00000   [ anon ]
20000000  309248 rwxs- 0000000000000000 000:00004   [ shmid=0x30004 ]
427d8000     120 r-x-- 0000000000000000 0fd:00000 ld-2.12.so
427f6000       4 r-x-- 000000000001d000 0fd:00000 ld-2.12.so
427f7000       4 rwx-- 000000000001e000 0fd:00000 ld-2.12.so
427fa000       4 r-x-- 0000000000000000 0fd:00000 libaio.so.1.0.1
427fb000       4 rwx-- 0000000000000000 0fd:00000 libaio.so.1.0.1
427fe000    1572 r-x-- 0000000000000000 0fd:00000 libc-2.12.so
42987000       4 ----- 0000000000189000 0fd:00000 libc-2.12.so
42988000       8 r-x-- 0000000000189000 0fd:00000 libc-2.12.so
4298a000       4 rwx-- 000000000018b000 0fd:00000 libc-2.12.so
4298b000      12 rwx-- 0000000000000000 000:00000   [ anon ]
42990000      12 r-x-- 0000000000000000 0fd:00000 libdl-2.12.so
42993000       4 r-x-- 0000000000002000 0fd:00000 libdl-2.12.so
42994000       4 rwx-- 0000000000003000 0fd:00000 libdl-2.12.so
42997000      92 r-x-- 0000000000000000 0fd:00000 libpthread-2.12.so
429ae000       4 r-x-- 0000000000016000 0fd:00000 libpthread-2.12.so
429af000       4 rwx-- 0000000000017000 0fd:00000 libpthread-2.12.so
429b0000       8 rwx-- 0000000000000000 000:00000   [ anon ]
429b4000     160 r-x-- 0000000000000000 0fd:00000 libm-2.12.so
429dc000       4 r-x-- 0000000000027000 0fd:00000 libm-2.12.so
429dd000       4 rwx-- 0000000000028000 0fd:00000 libm-2.12.so
429f6000      28 r-x-- 0000000000000000 0fd:00000 librt-2.12.so
429fd000       4 r-x-- 0000000000006000 0fd:00000 librt-2.12.so
429fe000       4 rwx-- 0000000000007000 0fd:00000 librt-2.12.so
45a32000      92 r-x-- 0000000000000000 0fd:00000 libnsl-2.12.so
45a49000       4 r-x-- 0000000000016000 0fd:00000 libnsl-2.12.so
45a4a000       4 rwx-- 0000000000017000 0fd:00000 libnsl-2.12.so
...
mapped: 462172K    writeable/private: 5064K    shared: 309248K
[root@study1 ~]# 
這裡就很明白了。這裡的lib*.so是會被很多process load自己的執行環境中,都被ps計算到rss中。
從pmap最後一行的輸出中: 
    writeable/private: 5064K   :這個才是程式真正佔用的實體記憶體。
 
再以top命令看看:
[root@study1 ~]# top -p 22922
top - 09:24:15 up 15:57,  3 users,  load average: 0.10, 0.18, 0.17
Tasks:   1 total,   0 running,   1 sleeping,   0 stopped,   0 zombie
Cpu(s):  1.0%us,  5.8%sy,  0.0%ni, 90.4%id,  2.3%wa,  0.2%hi,  0.3%si,  0.0%st
Mem:   1507836k total,  1442392k used,    65444k free,    33732k buffers
Swap:  2097144k total,   307124k used,  1790020k free,   559744k cached
 
  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                                                
22922 oracle    20   0  451m  28m  26m S  0.0  1.9   0:00.22 oracle  
 
這兒SHR(共享記憶體)=26m RES=28m, 28-26=2m(實際佔用的實體記憶體,這個與上面的pmap有點差異)
 
在看看Oracle記憶體的統計:
SQL> select spid,
        addr,
  2    3          round(pga_used_mem / 1024 / 1024, 0) pga_used_mem,
  4          round(pga_alloc_mem / 1024 / 1024, 0) pga_alloc_mem,
  5          round(PGA_FREEABLE_MEM / 1024 / 1024, 0) PGA_FREEABLE_MEM,
  6          round(pga_max_mem / 1024 / 1024, 0) pga_max_mem
  7     from v$process
  8    where spid = &id;
Enter value for id:                22922
old   8:   where spid = &id
new   8:   where spid =                22922
 
SPID                     ADDR     PGA_USED_MEM PGA_ALLOC_MEM PGA_FREEABLE_MEM PGA_MAX_MEM
------------------------ -------- ------------ ------------- ---------------- -----------
22922                    31DFDD20            1             1                0           1
 
pga為1m,與通過top計算的差不多。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/195110/viewspace-764322/,如需轉載,請註明出處,否則將追究法律責任。

相關文章