首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >理解JVM内存优化

理解JVM内存优化
EN

Stack Overflow用户
提问于 2017-10-13 10:31:30
回答 1查看 452关注 0票数 1

最近,我承担了在Java服务器中测试和优化内存利用率的任务,同时修复内存泄漏(如果有的话)。我们有4台JVM服务器运行在一台具有15G物理内存和32G交换内存的机器上。下面是free -m快照。

代码语言:javascript
复制
              total        used        free         shared  buff/cache    available
Mem:          15289       14786         392           1         110         342
Swap:         32767        3776       28991

如果我理解正确:-

  1. 大部分物理内存正在使用,大部分交换内存是空闲的。
  2. 内存的不足实际上是缓冲的。
  3. 我有48 of的虚拟内存

现在,我的每台服务器都使用7G最大堆大小设置了-Xmx选项。下面是GC Utils的输出

代码语言:javascript
复制
$ jstat -gcutil 8317
  S0     S1     E      O      M     CCS      YGC     YGCT    FGC    FGCT     GCT
  0.00   0.00   6.97   0.22  96.77  91.89     72    8.027    33   10.975   19.002
$ jstat -gcutil 8332
  S0     S1     E      O      M     CCS      YGC     YGCT    FGC    FGCT     GCT
  0.00   0.00   5.17  50.76  96.57  91.65    274   51.001    51  179.106  230.107
$ jstat -gcutil 8249
  S0     S1     E      O      M     CCS      YGC     YGCT    FGC    FGCT     GCT
  0.00   2.10  80.37  69.53  96.87  92.08    421   69.478    13   56.569  126.047
$ jstat -gcutil 23875
  S0     S1     E      O      M     CCS      YGC     YGCT    FGC    FGCT     GCT
 27.91   0.00  37.07  86.29  97.59  94.60    232    7.294     2    0.030    7.324

在运行手动全GC之后,它完全释放了所有服务器的年轻一代和老一代。现在我需要帮助来理解这一特性,基本上,我是否正确地假设了以下几点?

  1. 对象的移动取决于寿命和生存计数作为伊甸园-> S0 -> S1 -> O。
  2. 三台服务器都有“老一代”>“年轻将军”,这是否意味着整个GC没有足够的运行?
  3. 或者,我需要调整SurvivorRatio和NewRatio等设置,让年轻一代有更多的机会收集对象,并延迟将对象移动到旧空间。
  4. 不管Y空间的增加意味着GC的速度慢,应用程序吞吐量差,我是否应该增加内存,不再担心调整?

我问这个问题,因为完整的GC确实释放了所有内存,所以没有内存泄漏,但是我如何通过调整GC设置来在内存使用和应用程序槽之间取得平衡。有人能提供更多的方向或建议,考虑上述机器状态吗?

代码语言:javascript
复制
JVM Details:
Java Version: openjdk version "1.8.0_131" Server Class
GC: Parallel Collector(Default one)
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-10-13 13:14:08

简而言之:如果你想了解你的系统,基本上在某个时间点使用内存是个坏主意。随着时间的推移,观察这种行为会有更大的帮助。要做到这一点,请使用枯萎的JConsole或专业分析器(如YourKit或JProfiler )。另一方面,Hotspot-VM的缺省值是相当合理的,因此除非您有一个非常具体的应用程序-内存配置文件,否则您可能不会通过摆弄而赢得更多的好处,只需在问题上抛出更多的硬件即可。

请注意,您的服务器很可能是低维度的(见问题4)。

较长的答覆:

问题1:对象如何通过不同的内存区域?每个对象都是在伊甸园空间中创建的。第一个小垃圾收集(也会触发一个主要的收集)将该对象放置在幸存者(如果有足够的空间)或直接进入终身。对于幸存者中已经存在的对象,它们从一个幸存者空间移动到另一个幸存者空间,并且在某个时刻(由VM中的启发式确定)被移动到永久空间。规则总是成立的,至少有一个幸存者总是空的。

问题2:对老年人的职业比年轻时更多,你收集的不够多吗?绝对不是那么回事。如果很少执行Java中的垃圾收集,效果会更好(更有效)。基本上,如果有更多的对象在上一次集合之后死亡,则集合会更高效,因为它可以一次清理更多的内存。gc的设计是让终身填充直到它达到一个非常高的填充水平(接近100%),然后触发一个完整的gc。我们观察到生产系统在几周内没有完成一个完整的gc,因为年轻一代足够大以至于所有临时分配都在伊甸园或幸存者体内死亡。除此之外,你所有的缓存,春豆或其他任何东西都将被永久保存。

问题3:应该调整内存参数以优化内存消耗吗?当然:不!除非你知道你在做什么,否则永远不要碰那些东西。扩大年轻一代可能会导致你的应用程序因内存不足而失效。您应该非常清楚您的应用程序在处理这些内容之前的长期行为,而且hotspot的启发式非常好。另一方面,如果你知道你在做什么,那就有可能大大减少gc的次数。在一个系统(上面提到的一个)中,我们看到小集合从一次~20秒减少到几分钟一次,并且在调整后几乎完全停止了。但是在学习和理解的过程中,随着时间的推移,我们的应用程序是如何表现记忆的,我们也杀死了很多的执行。

问题4:应该增加内存而不是篡改吗?视情况而定。你的系统是不健康的。增加记忆会使情况更糟。您正在一个拥有16g物理内存的系统上运行堆高达7g (总计28g)的4个VM。如果所有VM都将内存消耗扩大到最大,您将看到大量的交换,这肯定会将性能降低到您难以想象的水平。在这个场景中,我会选择更多的硬件,特别是考虑到java应用程序的实际消耗大约是堆的1.5倍(您必须添加permgen/metaspace、堆栈、代码缓存和vm本身消耗的内存)。如果您确实知道,您的应用程序是使用-xmx7g运行的,那么您可以从这里开始:增加整体内存,同时减少旧的部分,这样绝对老的大小保持不变。然而,这意味着更多的硬件。

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

https://stackoverflow.com/questions/46727858

复制
相关文章

相似问题

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