Linux-Kernel

Linux(非透明)每程序大頁記帳

  • August 6, 2015

我最近將一些 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,我不知道。

引用自:https://serverfault.com/questions/527085