Linux(非透明)每程序大頁記帳
我最近將一些 java 應用程序轉換為使用 linux 手動配置的大頁面執行,如此處所述。我指出“手動配置”是因為它們不是 透明的大頁面,這給我們帶來了一些性能問題。
所以現在,我在一個系統上執行了大約 10 個 tomcat,我很想知道每個 tomcat 使用了多少記憶體。
我可以按照Linux Huge Pages Usage Accounting
/proc/meminfo
中的描述獲取摘要資訊。但我找不到任何工具可以告訴我實際的每個程序的大頁面使用情況。
我四處
/proc/pid/numa_stat
尋找,發現了一些有趣的資訊,這些資訊使我感到如此粗暴:function pshugepage () { HUGEPAGECOUNT=0 for num in `grep 'anon_hugepage.*dirty=' /proc/$@/numa_maps | awk '{print $6}' | sed 's/dirty=//'` ; do HUGEPAGECOUNT=$((HUGEPAGECOUNT+num)) done echo process $@ using $HUGEPAGECOUNT huge pages }
或者這個,在 perl 中:
sub counthugepages { my $pid=$_[0]; open (NUMAMAPS, "/proc/$pid/numa_maps") || die "can't open numa_maps"; my $HUGEPAGECOUNT=0; while (my $line=<NUMAMAPS>) { next unless ($line =~ m{ huge }) ; next unless ($line =~ m{dirty=}); chomp $line; $line =~ s{.*dirty=}{}; $line =~ s{\s.*$}{}; $HUGEPAGECOUNT+=$line; } close NUMAMAPS; # we want megabytes out, but we counted 2-megabyte hugepages return ($HUGEPAGECOUNT*2); }
它給我的數字是合理的,但我遠不相信這種方法是正確的。
環境是四核戴爾,64GB 記憶體,RHEL6.3,oracle jdk 1.7.x(目前為 20130728)
更新:Red Hat 現在建議在 RHEL5/6 上使用這種方法來處理巨頁記帳:
grep -B 11 'KernelPageSize: 2048 kB' /proc/[PID]/smaps \ | grep "^Size:" \ | awk 'BEGIN{sum=0}{sum+=$2}END{print sum/1024}'
我在 procps-ng 開發人員的郵件列表中問過這個問題。有人告訴我:
幾個月前在 procps-ng/pmap 工具中引入了大頁面支持(開關 -XX、-C、-c、-N、-n 應該允許您配置和顯示正在執行的核心支持的任何條目)。
我在 Fedora 19 上使用 procps-3.3.8 對此進行了一些實驗。我認為它沒有給我任何我從問題中建議的內容中沒有得到的資訊,但至少它具有權威的光環。
FWIW我最終得到以下結果:
.pmaprc 文件包含:
[Fields Display] Size Rss Pss Referenced AnonHugePages KernelPageSize Mapping [Mapping] ShowPath
然後我使用以下命令來提取大頁面資訊:
pmap -c [process id here] | egrep 'Add|2048'
在 grep 中,“添加”用於標題行。“2048”將抓取核心頁面大小為 2048 的任何內容,即大頁面。它還會抓取不相關的東西。
這是一些範例輸出:
Address Size Rss Pss Referenced AnonHugePages KernelPageSize Mapping ed800000 22528 0 0 0 0 2048 /anon_hugepage (deleted) f7e00000 88064 0 0 0 0 2048 /anon_hugepage (deleted) fd400000 45056 0 0 0 0 2048 /anon_hugepage (deleted) 7f3753dff000 2052 2048 2048 2048 2048 4 [stack:1674] 7f3759000000 4096 0 0 0 0 2048 /anon_hugepage (deleted) 7f3762d68000 2048 0 0 0 0 4 /usr/lib64/libc-2.17.so 7f376339b000 2048 0 0 0 0 4 /usr/lib64/libpthread-2.17.so
我們只關心 kernelPageSize 為 2048 的行。
我認為它告訴我我已經在大頁面中分配了 159744 KB (22528+88064+45056+4096) 的 RAM。我告訴 java 使用 128M 作為它的堆,它還有一些其他的記憶體池,所以這是一個合理的數字。Rss & Referenced 0 不太有意義,但是測試 java 程序非常簡單,所以它也是合理的。
它與我從上面的 perl 片段中得到的數字不一致,因為 perl 只搜尋“臟”頁面 - 那些實際使用過的頁面。和/或因為 perl 是錯誤的,我不知道。
我還在 RHEL6 機器上嘗試了 procps 3.3.9,其中一些活動的 tomcat 使用了大量的大頁記憶體。Rss & Referenced 列都是 0。這很可能是核心的錯,而不是 procps,我不知道。