首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Docker容器中运行的JVM的驻留集大小(RSS)和Java总提交内存(NMT)之间的差异

Docker容器中运行的JVM的驻留集大小(RSS)和Java总提交内存(NMT)之间的差异
EN

Stack Overflow用户
提问于 2016-07-27 03:04:47
回答 1查看 26.1K关注 0票数 49

场景:

我有一个在docker容器中运行的JVM。我使用两个工具做了一些内存分析: 1) Java 2) Native memory Tracking。这些数字看起来令人困惑,我正在试图找出导致差异的原因。

问题:

对于Java进程,RSS报告为1272MB,总Java内存报告为790.55 MB。我如何解释剩余的内存1272 - 790.55 = 481.44 MB到哪里去了?

即使在SO:上查看了 之后,我仍要保留此问题的原因:

我确实看到了答案,这个解释是有道理的。但是,在从Java NMT和pmap -x获得输出后,I仍然不能具体地映射哪些java内存地址是实际驻留的和物理映射的。我需要一些具体的解释(带有详细的步骤)来找出是什么导致了RSS和Java总提交内存之间的差异。

顶部输出

Java NMT

Docker内存统计信息

Graphs

我有一个码头集装箱运行了超过48小时。现在,当我看到一个包含以下内容的图表时:

  1. 分配给停靠容器的总内存=2 GB
  2. Java最大堆=1 GB
  3. 提交的总内存(JVM) =始终少于800 MB的
  4. 已使用的堆(JVM) =始终少于200 MB的

<代码>H135未使用的堆(JVM) =始终小于100 MB。<代码>H236<代码>H137RSS=大约1.1 GB。<代码>H238<代码>G239

那么,是什么在消耗1.1 GB (RSS)和800MB (Java总提交内存)之间的内存呢?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-07-30 14:05:21

你从Mikhail Krestjaninoff的" Analyzing java memory usage in a Docker container“中得到了一些线索

(需要明确的是,三年后的2019年5月,the with openJDK 8u212 )

Resident Set Size是进程当前分配和使用的物理内存量(没有换出页面)。它包括代码、数据和共享库(在使用它们的每个进程中都会计入)

为什么docker统计信息与ps数据不同?

第一个问题的答案非常简单- Docker has a bug (or a feature - depends on your mood):它将文件缓存包括到总内存使用信息中。因此,我们可以避免使用这个指标,而使用关于RSS的ps信息。

好吧,好吧--但是为什么RSS比Xmx要高呢?

理论上讲,在java应用程序的情况下

RSS = Heap size + MetaSpace + OffHeap size

其中OffHeap由线程堆栈、直接缓冲区、映射文件(库和jars)和

代码组成

JDK 1.8.40开始,我们就有了!

如您所见,我已经向JVM添加了-XX:NativeMemoryTracking=summary属性,所以我们可以从命令行调用它:

docker exec my-app jcmd 1 VM.native_memory summary

(这就是OP所做的)

不用担心“未知”部分-似乎NMT是一个不成熟的工具,不能处理CMS (当你使用另一个GC时,这一部分就消失了)。

请记住, NMT显示的是“已提交”内存,而不是“常驻内存”(通过ps命令获得)。换句话说,内存页面可以在不考虑驻留(直到它被直接访问)的情况下被提交。,这意味着非堆区域(堆始终是预初始化的)的NMT结果可能大于RSS值

(这就是"Why does a JVM report more committed memory than the linux process resident set size?“的用武之地)

因此,尽管我们将

堆限制设置为256m,但我们的应用程序消耗了367M。“其他”164M主要用于存储类元数据、编译代码、线程和GC数据。

前三个点通常是应用程序的常量,因此唯一随堆大小增加的是GC数据。

这种依赖关系是线性的,但“k”系数(y = kx + b)远小于1。

更普遍的是,issue 15020似乎紧随其后,它报告了一个类似的问题,从docker1.7开始

我正在运行一个简单的

应用程序,它将大量数据加载到内存和从内存中读出。

我将JVM设置为8G堆(-Xmx8G)。我有一台132G内存的机器,它不能处理超过7-8个容器,因为它们的增长远远超过了我对JVM施加的8G限制。

(docker statreported as misleading before,因为它显然将文件缓存包含在总内存使用信息中)

docker stat显示,每个容器本身使用的内存比JVM应该使用的内存多得多。例如:

CONTAINER CPU % MEM USAGE/LIMIT MEM % NET I/O
dave-1 3.55% 10.61 GB/135.3 GB 7.85% 7.132 MB/959.9 MB
perf-1 3.63% 16.51 GB/135.3 GB 12.21% 30.71 MB/5.115 GB

看起来像是JVM向OS请求内存,内存是在容器中分配的,JVM在GC运行时释放内存,但容器不会将内存释放回主操作系统。所以..。内存泄漏。

票数 55
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38597965

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档