首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在“摘要”模式下Java本机内存跟踪的开销是什么?

在“摘要”模式下Java本机内存跟踪的开销是什么?
EN

Stack Overflow用户
提问于 2022-07-26 15:34:46
回答 2查看 459关注 0票数 6

我想知道通过‑XX:NativeMemoryTracking=summary启用NMT的真正/典型开销是什么(我想要的完整命令选项是-XX:+UnlockDiagnosticVMOptions ‑XX:NativeMemoryTracking=summary ‑XX:+PrintNMTStatistics)

我在任何地方都找不到很多信息--无论是在博客上还是在官方文档上。医生说:

注意:启用NMT会导致5% -10%的性能开销

但是他们没有说明哪种模式会产生这种性能开销(包括摘要和细节)?这种开销实际上是(CPU,内存,.)。在本机内存跟踪指南中,他们声称:

启用NMT将导致JVM性能下降5-10 %,NMT的内存使用会将2个机器单词作为malloc头添加到所有malloc内存中。NMT也会跟踪NMT内存的使用情况。

但同样,摘要模式和细节模式都是这样吗?

我想要的基本上是,为生产应用程序永久添加‑XX:NativeMemoryTracking=summary是否安全(类似于连续的JFR记录),以及潜在的成本。到目前为止,在我们的应用程序上测试这个时,我没有发现有什么不同,但很难

是否有权威的信息来源,包含有关此性能开销的更多详细信息?有人有为生产应用程序永久启用此功能的经验吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-07-29 14:12:16

本地内存跟踪的开销显然取决于应用程序分配本机内存的频率。通常,在Java应用程序中,这种情况并不常见,但情况可能有所不同。由于您已经尝试过并且没有注意到性能差异,所以您的应用程序显然也不是一个例外。

summary模式下,本机内存跟踪大致完成以下操作:

  • 将JVM中的每个malloc请求增加2个机器字(16个字节);
  • 在这两个单词中记录分配大小和标志;
  • 原子递增(或在free上递减)对应于给定内存类型的计数器;
  • 除了mallocfree之外,它还处理虚拟内存预留和新领域分配的更改,但这些更改甚至比malloc/free调用更少。

因此,对我来说,开销是相当小的;5-10%肯定是一个很大的高估(对于收集和存储堆栈跟踪的detail模式来说,这些数字是有意义的,这很昂贵,但summary不这样做)。

当许多线程同时分配/释放本机内存时,原子计数器的更新可能成为瓶颈,但同样,这更像是一种极端情况。简而言之,如果您测量了一个实际的应用程序,并且没有注意到任何退化,那么在生产中启用NMT摘要可能是安全的。

票数 5
EN

Stack Overflow用户

发布于 2022-07-30 12:49:48

免责声明:我的答案是基于JDK 18,我所写的大部分内容对于旧版本都是有效的。当你有疑问的时候,你需要自己来衡量。

背景:

NMT跟踪通过Direct缓冲区完成的热点VM内存使用和内存使用情况。基本上,它连接到malloc/free和mmap/munmap调用并进行计算。

它不跟踪其他JDK内存使用情况( hotspot VM外部)或第三方库的使用情况。这在这里很重要,因为它使NMT行为在某种程度上可以预测。Hotspot试图通过malloc避免细粒度的分配。相反,它依赖于自定义内存管理器,如Arenas、代码堆或Metaspace。

因此,对于大多数应用程序来说,hotspot中的mallocs/mmap并不是那么“热”,也不是很大。

我将把重点放在malloc/free上,因为它们的数量远远超过mmap/munmap的数量:

内存成本:

  1. (detail+summary):每malloc() 2字
  2. (仅提供详细信息):Malloc站点表
  3. (detail+summary):vm映射和线程堆栈的映射列表

这里,(1)完全矮小(2)和(3)。因此,摘要模式和细节模式之间的内存开销并不显著。

请注意,甚至(1)也可能没有那么重要,因为基础libc分配器已经规定了可能大于(纯分配大小+ 16字节malloc报头)的最小分配大小。因此,需要测量NMT内存开销实际转化为RSS增加的程度。

总共有多少内存开销,这意味着无法回答,因为JVM内存成本通常由堆大小决定。因此,将RSS与NMT成本进行比较几乎是毫无意义的。但是仅举一个例子,对于具有1GB预触摸堆NMT内存开销的spring memory来说,大约是0.5%。

根据我的经验,NMT内存开销仅在病理情况下或在导致JVM进行大量细粒度分配的角落情况下才起作用。如果一个人做了疯狂的类加载量。但通常情况下,您希望启用NMT,以查看正在发生的事情。

业绩成本:

NMT确实需要一些同步。在摘要模式中,它原子地增加每个malloc/free上的计数器。

在详细模式中,它做了更多的工作:

  • 捕获malloc站点上的调用堆栈
  • 查找哈希映射中的调用堆栈
  • 增加散列映射入口计数器

这需要更多的周期。散列映射是无锁的,但仍然使用原子操作进行修改。它看起来很昂贵,特别是如果hotspot处理了来自不同线程的许多错误。情况到底有多糟?

最坏情况例子

微基准,64 malloc分配(通过Unsafe.allocateMemory())由100个并发线程完成,在一台24核心机器上:

代码语言:javascript
复制
NMT off:        6   secs
NMT summary:    34  secs
NMT detail:     46  secs

看上去很疯狂。然而,这在实践中可能并不重要,因为这不是现实生活的例子。

弹簧启动,平均10次:

代码语言:javascript
复制
NMT off:               3.79 secs
NMT summary:           3.79 secs  (+0%)
NMT detail:            3.91 secs  (+3%)

所以,这里,没那么糟。摘要模式的成本实际上在测试噪声中消失了。

文艺复兴,哲学家的基准

有趣的例子,因为这做了大量的同步,导致许多对象监视器被膨胀,而这些是错误的:

平均基准分数:

代码语言:javascript
复制
NMT off:               4697
NMT summary:           4599  (-2%)
NMT detail:            4190  (-11%)

有些介于另外两个例子之间。

结论

没有明确的答案。

内存和性能成本都取决于JVM进行了多少分配。

对于正常的行为良好的应用程序来说,这个数字很小,但是在病态情况下(例如JVM错误),以及在一些由用户程序引起的情况下(例如,大量的类加载或同步),这个数目可能很大。可以肯定的是,你需要衡量一下自己。

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

https://stackoverflow.com/questions/73126185

复制
相关文章

相似问题

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