最近,我承担了在Java服务器中测试和优化内存利用率的任务,同时修复内存泄漏(如果有的话)。我们有4台JVM服务器运行在一台具有15G物理内存和32G交换内存的机器上。下面是free -m快照。
total used free shared buff/cache available
Mem: 15289 14786 392 1 110 342
Swap: 32767 3776 28991如果我理解正确:-
现在,我的每台服务器都使用7G最大堆大小设置了-Xmx选项。下面是GC Utils的输出
$ 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之后,它完全释放了所有服务器的年轻一代和老一代。现在我需要帮助来理解这一特性,基本上,我是否正确地假设了以下几点?
我问这个问题,因为完整的GC确实释放了所有内存,所以没有内存泄漏,但是我如何通过调整GC设置来在内存使用和应用程序槽之间取得平衡。有人能提供更多的方向或建议,考虑上述机器状态吗?
JVM Details:
Java Version: openjdk version "1.8.0_131" Server Class
GC: Parallel Collector(Default one)发布于 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运行的,那么您可以从这里开始:增加整体内存,同时减少旧的部分,这样绝对老的大小保持不变。然而,这意味着更多的硬件。
https://stackoverflow.com/questions/46727858
复制相似问题