长GC在应用程序中暂停

我目前正在运行一个需要最大堆大小为16GB的应用程序。

目前我使用以下标志来处理垃圾收集。

-XX\:+UseParNewGC, -XX\:+UseConcMarkSweepGC, -XX:CMSInitiatingOccupancyFraction=50, -XX\:+DisableExplicitGC, -XX\:+PrintGCDateStamps, -XX\:+PrintGCDetails, -Xloggc\:/home/user/logs/gc.log 

但是,我注意到在一些垃圾收集期间,应用程序会锁定几秒钟然后继续 – 这是完全不可接受的,因为它是游戏服务器。

我的垃圾收集日志可以在这里找到。

关于我应该改变什么以减少这些长时间停顿的任何建议将不胜感激。

关于我应该改变什么以减少这些长时间停顿的任何建议将不胜感激。

可能是CMS GC无法跟上系统产生的垃圾量。 但是,GC必须执行的工作实际上与系统保留的非垃圾量密切相关。

所以……

  • 尽量减少应用程序的实际内存使用量; 例如,不要缓存这么多东西,或减少你的“世界”的大小。
  • 尝试降低应用程序生成垃圾的速度。
  • 升级到具有更多核心的计算机,以便在必要时有更多可用于运行并行GC线程的核心。

致神秘主义者:

是的,事后看来,用C ++实现服务器可能更好。 但是,我们对“游戏”一无所知。 如果它涉及具有复杂异构数据结构的复杂世界模型,那么在C ++中实现它可能意味着您将服务器崩溃的问题替换为“GC暂停”问题,因为它管理其数据的方式存在问题结构。

看着你的日志,我看不到任何长时间的停顿。 但年轻的GC非常频繁。 虽然促销率很低(大多数垃圾都被年轻的GC清除了)。 同时你的旧空间利用率很低。

BTW我们在谈论Minecraft服务器吗?

为了减少年轻GC的频率,你应该增加它的大小。 我建议从-XX:NewSize=8G -XX:MaxNewSize=8G开始-XX:NewSize=8G -XX:MaxNewSize=8G

对于如此大的年轻空间,您还应该减少幸存者空间大小-XX:SurvivorRatio=512

GC调整是一个试验和错误的路径,因此您可能需要更多的迭代和调整。

您可以在mu blog找到几篇有用的文章

  • HotSpot JVM GC选项备忘单
  • 了解HotSpot JVM中的年轻GC暂停

我不是Java垃圾收集方面的专家,但假设服务器有多个处理器,看起来你使用并发收集器(UseConcMarkSweepGC标志)做了正确的事情。 请按照http://www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html#cms上的故障排除建议进行操作。 如果您已经拥有,请告诉我们您尝试时发生了什么。

你使用的是哪个版本的java? http://docs.oracle.com/javase/7/docs/technotes/guides/vm/G1.html为了更好地尝试最小化类中实例变量的使用。对局部变量执行比实例更好varibles。它有助于获得性能并避免同步问题。在程序退出之前的操作结束时,如果使用实例变量,则始终重置已使用的变量,并在需要时再次设置。 它有助于提高性能。除了java版本之外,还实现了一个很好的垃圾收集策略。如果可行的话,最好转移到新版本。 您还可以通过VisualVm监视垃圾收集器暂停时间,并且可以在执行更多垃圾收集时获得更多信息。