4

我正在尝试测量 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

4 回答 4

3
  1. 要看。
    • 许多共享内存映射smaps直接由磁盘上的库/二进制文件支持。虽然这些的占用空间确实很重要,但它并不那么重要,因为系统可以随时删除这些页面并在再次需要时从磁盘重新加载它们。
    • 任何脏的或私有的东西都只属于当前进程(好吧,如果你的程序在没有执行程序的情况下分叉,则为进程树)。这一点更重要,因为如果系统需要将这些页面推出内存,则必须将它们保存为交换。
    • 地块测量的可能与后者相关。但是,JVM 本身(没有您的程序)占用的内存在两者中。
  2. 是的。Java 或其使用的库可能会根据可用 RAM 的大小调整其内存模型。在不同的架构上,您使用完全不同的二进制文件,这些二进制文件可能更大或更小,或者排列方式不同,或者使用不同的 JIT 和内存管理策略。
于 2009-12-11T18:54:37.887 回答
3

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

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

  • 马匿名映射内存
    • .p 私有
      • .d 脏 == malloc/mmapped 堆和堆栈分配和写入的内存
      • .c clean == malloc/mmapped 堆和堆栈内存一旦分配、写入、然后释放,但尚未回收
    • .s 共享
      • .d 脏 == 应该没有
      • .c clean == 应该没有
  • Mn 命名映射内存
    • .p 私有
      • .d 脏 == 文件映射写入内存私有
      • .c clean == 映射程序/库文本私有映射
    • .s 共享
      • .d 脏 == 文件映射写入内存共享
      • .c clean == 映射库文本共享映射

我宁愿按以下方式获取数字,以便以最少的开销获得实数。
您必须将这些总结起来才能将 ps 显示为 RSS 的内容进行划分,并获得更准确的数字以免混淆。
/proc/(pid)/status 试图显示这些数字,但它们失败了。
因此,与其尝试将 [anon]、[stack] 正确标记到每个映射,我希望 linux 内核人员将主线 proc 入口代码汇总并显示这些 Mapd、Mapc、Mnpd ......数字。
嵌入式 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_Clean/{if(anon) {asum+=$2}else{nasum+=$2}} END{printf "sum=%d\n",asum}' /proc/<pid>/smaps

Mnpd:……等等

于 2010-01-04T14:46:20.890 回答
1

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

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

于 2009-12-11T18:46:24.507 回答
0

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

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

于 2009-12-11T18:47:00.980 回答