测量Linux上进程的内存使用情况

时间:2009-12-11 18:33:20

标签: java linux memory-management valgrind

我正在尝试测量linux上进程(java程序)的内存使用情况,并有两个与此相关的问题:

  1. 我尝试使用脚本ps_mem.py(来自/ proc / $ PID / smaps的值)和总内存使用量的峰值约为135MB(私有和共享内存)。共享内存量小于1MB。尝试使用Valgrind与massif工具valgrind --tool=massif --trace-children=yes --stacks=yes java myProgram在内存使用高峰时产生大约10MB 根据我的理解,堆是存储程序变量的地方,这是否意味着两个方法之间的差异是代码本身占用的空间(包括jvm)?

  2. 如果相同的程序有不同的RAM或/和使用不同的处理器(ARM或x86),它们是否在不同的机器上使用不同的内存量?

4 个答案:

答案 0 :(得分:3)

  1. 取决于。
    • smaps中的许多共享内存映射都由磁盘上的库/二进制文件直接支持。虽然它们的占地面积很重要,但它不那么重要,因为系统可以随时丢弃这些页面,并在需要时再次从磁盘重新加载它们。
    • 任何脏或私有的东西都只属于当前进程(如果你的程序没有高级分支,那么进程树)。这一点更为重要,因为如果需要将这些页面从内存中推出,系统必须将它们保存为交换。
    • 测量的地块可能与后者有关。但是,JVM本身(没有你的程序)占用的内存都在。
  2. 是。 Java或它使用的库可能会根据可用RAM的大小调整其内存模型。在不同的体系结构中,您使用完全不同的二进制文件,这些二进制文件可能更大或更小,或者以不同的方式排列或使用不同的JIT和内存管理策略。

答案 1 :(得分:3)

除此之外还有一个类似的问题,在这里回答同样的问题,让人们知道linux proc stat vm info目前是不准确的。
Valgrind可以显示详细信息,但它会显着降低目标应用程序的速度,并且大多数时候它会改变应用程序的行为。

我假设每个人都想知道WRT“内存使用情况”如下...
在linux中,单个进程可能使用的物理内存量大致可分为以下几类。

  • M.a匿名映射内存
    • .p私有
      • .d dirty == malloc / mmapped堆和堆栈分配和写入内存
      • .c clean == malloc / mmapped堆和堆栈内存一旦分配,写入,然后释放,但尚未回收
    • .s分享
      • .d dirty ==应该没有
      • .c clean ==应该没有
  • M.n命名映射内存
    • .p私有
      • .d dirty == file mmapped write memory private
      • .c clean ==映射程序/库文本私有映射
    • .s分享
      • .d dirty ==文件mmapped书面内存共享
      • .c clean ==映射库文本共享映射

我更希望获得如下数字,以获得最少开销的实数 你必须总结这些,以便将ps显示为RSS并将更准确的数字分开而不要混淆 / proc /(pid)/ status试图显示这些数字,但它们都失败了 因此,我没有尝试将[anon],[stack]标记为正确地映射到每个映射,而是希望如此 Linux内核人员将主要处理proc入口代码以汇总并显示这些M.a.p.d,M.a.p.c,M.n.p.d,....数字。
嵌入式linux的人会很高兴恕我直言。

M.a.p.d:

 awk '/^[0-9a-f]/{if ($6=="") {anon=1}else{anon=0}} /Private_Dirty/{if(anon) {asum+=$2}else{nasum+=$2}} END{printf "sum=%d\n",asum}' /proc/<pid>/smaps

M.a.p.c:

 awk '/^[0-9a-f]/{if ($6=="") {anon=1}else{anon=0}} /Private_Clean/{if(anon) {asum+=$2}else{nasum+=$2}} END{printf "sum=%d\n",asum}' /proc/<pid>/smaps

M.n.p.d:......等等

答案 2 :(得分:1)

对于#1,共享内存是由多个进程使用的内存(可能)。这基本上是如果您在多个进程中运行相同的二进制文件或不同的进程正在使用共享库。堆是存储已分配内存的位置(在Java中使用new时)。由于Java有自己的VM,因此它会在您在java代码中看不到的进程级别分配大量内存。我认为是的,135 MB的大部分来自JVM代码/数据本身。但是,堆栈也占用了内存(当你进行函数调用并有局部变量时)。

对于#2,当我们让内存等于RAM +交换空间时,不同数量的RAM不会影响使用多少“内存”。但是,不同的处理器(特别是如果我们谈论的是32位与64位)可能会使用不同的内存量。此外,编译进程的方式可能会改变使用的内存量,因为您可以指示编译器优化内存占用超速,以及完全禁用部分或全部优化。

答案 3 :(得分:0)

您可能想看看JConsole。根据您的测量目的,事情可能会很棘手。如果您想知道Java程序的内存使用情况,那么测量进程内存使用情况的工具将是不准确的,因为它们将显示JVM和程序使用的内存。

至于massif工具,您应该知道JVM的某些部分将存储在堆栈中,并且Java代码本身可能在堆上(因为它是JVM的变量),我不太了解JVM说。