我试图测量一个进程(一个Java程序)在Linux上的内存使用情况,并有两个相关的问题:
我尝试使用脚本ps_mem.py (从/ proc / $ PID / smaps总结值),总内存使用率的峰值大约是135MB(私有和共享内存)。 共享内存量小于1MB。 尝试使用Valgrind与山体工具valgrind --tool=massif --trace-children=yes --stacks=yes java myProgram
在内存使用高峰时产生大约10MB。
现在,据我了解,堆是我的程序的variables存储的地方,这是否意味着这两个方法之间的区别是代码本身(包括jvm)所占用的空间?
如果同一程序在不同的机器上使用不同数量的内存,或者使用不同的处理器(ARM或x86),它们的内存是不同的吗?
smaps
中的许多共享内存映射直接由磁盘上的库/二进制文件支持。 尽管它们的占用空间很重要,但它并不重要,因为系统可以随时丢弃这些页面,并在需要时再次从磁盘重新加载它们。 除此之外,还有一个类似的问题,在这里回答同样的问题,让人们知道当前的linux proc stat vm信息不准确。
Valgrind可以显示详细信息,但会显着降低目标应用程序的速度,并且大部分时间会改变应用程序的行为。
我假设每个人都想知道WRT“内存使用情况”是以下…
在Linux中,单个进程可能使用的物理内存量大致可以分为以下几类。
我宁愿得到的数字如下,以最小的开销获得实数。
你必须总结这些以便将RSS节目分为RSS,并获得更准确的数字而不会混淆。
/ proc /(pid)/状态试图显示这些数字,但他们失败。
因此,我不希望为每个映射正确地标记[anon],[stack],我希望Linux内核人员将mainline proc入口代码汇总并显示这些Mapd,Mapc,Mnpd,…数字。
嵌入式Linux的人将会得到真正的快乐恕我直言。
MAPD:
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
MAPC:
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
Mnpd:…等等
对于#1,共享内存是内存(可能)被多个进程使用。 这基本上是如果您在多个进程中运行相同的二进制文件或不同的进程正在使用共享库。 堆是存储分配的内存的地方(当你在Java中使用new
时)。 由于Java有它的虚拟机,所以它在进程级别上分配了很多你在java代码中看不到的内存。 我认为是的,135 MB的大部分来自JVM代码/数据本身。 但是,也有堆栈占用的内存(当您进行函数调用并具有本地变量时)。
对于#2,当我们让内存等于RAM +交换空间时,不同数量的RAM不会影响使用多少“内存”。 但是,不同的处理器(特别是如果我们正在谈论32位与64位)可能会使用不同数量的内存。 而且,编译过程的方式可能会改变所使用的内存量,因为您可以指示编译器针对内存占用空间进行优化,同时完全禁用部分或全部优化。
你可能想看看JConsole。 根据测量的目的,事情可能会非常棘手。 如果您想了解Java程序的内存使用情况,那么测量进程内存使用情况的工具将会不准确,因为它们会显示JVM使用的内存以及程序。
至于massif工具,你应该知道JVM的一部分将被存储在堆栈上,并且java代码本身可能在堆上(因为它是JVM的一个变量),我不太了解JVM说。