小心……如果不谨慎,GC可能是一个棘手的话题。在任何运行时(Java的JVM/.Net的CLR)中,都会发生几个过程。通常会对内存进行早期优化(Young Generational Garbage Collection / Young Gen GC和Old Generational Garbage Collection / Old Gen GC)。年轻代垃圾回收经常发生,并且通常归因于您更小的暂停/抽搐。老年代垃圾回收通常是在看到长时间的“停止世界”暂停时正在进行的操作。
你可能会问为什么?当运行时清理堆时,您的运行时/JVM会出现暂停的原因是它必须经过所谓的相变。它停止运行应用程序的线程,以标记和交换指针以优化可用内存。年轻代更快,因为它主要释放只是临时对象。然而,老年代评估堆上的所有对象,并在内存耗尽时启动以释放非常需要的内存。
为什么要小心?旧的代在堆使用量增加时,暂停时间呈指数级增长。当总堆大小在2-4 GB时,你应该可以在像Java 6(JDK 1.6+)这样的现代运行时上正常运行。一旦超过这个阈值,你将看到暂停时间呈指数级增长。我曾经遇到一些客户需要重新启动服务器,因为在某些罕见情况下,如果堆很大,则GC暂停时间可能比完全重新启动还要长。
现在有一些新工具非常酷,可以帮助你评估GC是否是问题。其中之一是JHiccup,它可以从
azulsystems网站免费获取。目前我认为它只适用于Linux。他们还有一个JVM,具有重新构建的GC算法,可以无暂停地运行...但如果你在单个服务器部署中使用非关键应用程序,则可能不划算(该软件不免费)。
总之,如果您的运行时/JVM/CLR堆小于2GB,则增加更多内存将有所帮助。请确保给自己留一些余地。如果可能,永远不要达到100%的堆大小/内存大小。那时长时间暂停最长。给自己比您认为需要的多20%以上的内存。这样,您就有了优化移动对象的GC算法的空间。如果您曾经计划扩大规模......有一个工具可以修复约1990年的JVM技术(Azul Systems Zing JVM),但它不是免费的。他们提供了一个开源工具来诊断GC问题。JVM(我尝试过)还具有非常酷的线程级别可见性工具,可让您在生产中报告任何泄漏、错误或锁定而无需额外负担(使用JVM已经处理的数据和时间戳的某些技巧)。这节省了大量开发测试时间......但对于小型应用程序来说不适用。
保持在4GB以下。给予额外的余地。如果您想的话,可以打开这些标志来监视Java/JVM的GC:
java -verbose:gc myProgram
java -Xloggc:D:/log/myLogFile.log -XX:+PrintGCDetails myProgram
您可以尝试其他 Hotspot 使用的收集器,不止一个。
如果您使用 Linux,请尝试 JHiccup 工具。它是免费的。
CMSInitiatingOccupancyFraction
的默认值为 -1,而 CMS 使用的CMSTriggerRatio
默认值为 80。 - shaoyihe