Linux(非透明)每进程大页记帐

Dan*_*tts 5 linux java linux-kernel

我最近转变了一些Java应用程序与Linux的手动配置的大页面上运行,如所描述这里。我指出“手动配置”是因为它们不是 透明的大页面,这给我们带来了一些性能问题

所以现在,我在一个系统上运行了大约 10 个 tomcat,我很想知道每个 tomcat 使用了多少内存。

我可以/proc/meminfo按照Linux Huge Pages Usage Accounting 中的描述获取摘要信息。

但是我找不到任何工具来告诉我每个进程的实际大页面使用情况。

/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
}
Run Code Online (Sandbox Code Playgroud)

或者这个,在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);
}
Run Code Online (Sandbox Code Playgroud)

它给我的数字是合理的,但我远没有信心这种方法是正确的。

环境是四核dell,64GB ram,RHEL6.3,oracle jdk 1.7.x(当前为20130728)

Dan*_*tts 6

更新: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}'
Run Code Online (Sandbox Code Playgroud)

我在 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
Run Code Online (Sandbox Code Playgroud)

然后我使用以下命令来拉取大页面信息:

pmap -c [process id here] | egrep 'Add|2048'
Run Code Online (Sandbox Code Playgroud)

在 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
Run Code Online (Sandbox Code Playgroud)

我们只关心 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,我不知道。