我最近将一些 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 上使用这种方法来处理巨页记帐:
我在 procps-ng 开发人员的邮件列表中问过这个问题。有人告诉我:
我在 Fedora 19 上使用 procps-3.3.8 对此进行了一些实验。我认为它没有给我任何我从问题中建议的内容中没有得到的信息,但至少它具有权威的光环。
FWIW我最终得到以下结果:
.pmaprc 文件包含:
然后我使用以下命令来提取大页面信息:
在 grep 中,“添加”用于标题行。“2048”将抓取内核页面大小为 2048 的任何内容,即大页面。它还会抓取不相关的东西。
这是一些示例输出:
我们只关心 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,我不知道。
改进的 perl 脚本