Java 在Linux上测量进程的内存使用率

Java 在Linux上测量进程的内存使用率,java,linux,memory-management,valgrind,Java,Linux,Memory Management,Valgrind,我试图测量linux上进程(java程序)的内存使用情况,并提出两个相关问题: 我尝试使用该脚本(对/proc/$PID/smap中的值求和),总内存使用量的峰值约为135MB(私有和共享内存)。共享内存量小于1MB。尝试将Valgrind与massif工具一起使用Valgrind--tool=massif--trace children=yes--stacks=yes java myProgram在内存使用峰值时产生大约10MB的内存。 现在,据我所知,堆是存储程序变量的地方,这是否意味着这两

我试图测量linux上进程(java程序)的内存使用情况,并提出两个相关问题:

  • 我尝试使用该脚本(对/proc/$PID/smap中的值求和),总内存使用量的峰值约为135MB(私有和共享内存)。共享内存量小于1MB。尝试将Valgrind与massif工具一起使用
    Valgrind--tool=massif--trace children=yes--stacks=yes java myProgram
    在内存使用峰值时产生大约10MB的内存。
    现在,据我所知,堆是存储程序变量的地方,这是否意味着这两种方法之间的区别在于代码本身(包括jvm)占用的空间

  • 如果不同的机器具有不同数量的RAM或/或使用不同的处理器(ARM或x86),那么相同的程序在不同的机器上使用不同数量的内存吗

  • 对于#1,共享内存是多个进程(可能)使用的内存。基本上,如果在多个进程中运行同一个二进制文件,或者不同的进程使用共享库,则会出现这种情况。堆是存储分配内存的地方(在Java中使用
    new
    时)。由于Java有它的VM,它在进程级别上分配了大量Java代码中没有的内存。我认为是的,135MB中的大部分来自JVM代码/数据本身。但是,堆栈也占用了内存(当您进行函数调用并使用局部变量时)


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

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

    至于massif工具,您应该知道JVM的一部分将存储在堆栈上,java代码本身可能在堆上(因为它是JVM的一个变量),我对JVM的了解还不够

  • 视情况而定。
    • smap
      中的许多共享内存映射直接由磁盘上的库/二进制文件支持。虽然这些页面的占用空间很重要,但它并不重要,因为系统可以随时删除这些页面,并在需要时从磁盘重新加载它们
    • 任何脏的或私有的内容都只属于当前进程(如果程序分叉时没有exec,则为进程树)。这一点更为重要,因为如果需要将这些页面从内存中推出,系统必须保存它们以进行交换
    • 地块所测量的可能与后者有关。但是,JVM本身(没有您的程序)占用的内存在两者中都有
  • 对。Java或它使用的库可能会根据可用RAM的大小调整其内存模型。在不同的体系结构上,您使用的是完全不同的二进制文件,它们可能更大或更小,或者排列方式不同,或者使用不同的JIT和内存管理策略

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

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

    • 匿名映射内存
      • 私人
        • .d dirty==malloc/mmapped堆和堆栈分配和写入的内存
        • .c clean==malloc/mmapped堆和堆栈内存一旦分配、写入、然后释放,但尚未回收
      • s.共享
        • .d dirty==应该没有
        • .c clean==应该没有
    • M.n命名映射内存
      • 私人
        • .d dirty==文件映射的写入内存专用
        • .c clean==映射程序/库文本私有映射
      • s.共享
        • .d dirty==文件M映射的写入内存共享
        • .c clean==映射库文本共享映射
    我更愿意得到如下数字,以便以最少的开销得到实数。
    为了将ps显示为RSS的内容进行划分,并获得更准确的数字,您必须将这些数字相加。
    /proc/(pid)/status尝试显示这些数字,但失败。
    因此,我不想尝试将[anon]、[stack]正确地标记到每个映射,而是希望 linux内核人员将把进程条目代码作为主线,汇总并显示这些M.a.p.d、M.a.p.c、M.n.p.d。。。。数字。
    嵌入式linux用户会非常高兴的

    医学博士:

     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
    
    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//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
    
    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//smaps
    
    医学博士:。。。等等