客户端的最佳垃圾回收设置是什么?

5
近期的JVM有许多垃圾回收的XX参数(例如参见此处),但是哪些选项能使客户端Swing应用程序表现更好呢?
我应该注意到,客户端Java应用程序中真正令我恼火的事情之一就是停止整个垃圾回收所需的大量延迟。在Intelli-J IDEA中,我曾经看到它需要三分钟甚至更长时间。
编辑:感谢所有的回复。只是为了报告一下,我启用了CMS垃圾回收器,使用了这里建议的设置,这是一个很好的公共参考,大多数人都熟悉这种类型的应用程序。我还设置了-XX:+StringCache,以查看它是否能减少内存需求。
通常观察发现,使用字符串缓存选项不会明显降低正常运行性能。然而,内存的减少是巨大的。但是CMS方法不够彻底,需要一次停顿垃圾回收周期(返回到三分钟等待),以清除内存(在一个运行中达到了400MB)。
然而,鉴于内存占用减少,我可能只需要设置较小的最大内存量,这将使停顿垃圾回收的大小更小。
IDEA 8.1.4带有JDK 1.6.0_12,因此我尚未测试G1。此外,我的机器只有2个核心,因此G1方法无法最大化利用。是时候向老板要求更好的机器了;)。
5个回答

7
这个问题没有单一的答案,它高度取决于你的应用程序正在做什么以及如何管理其对象。也许可以查看垃圾回收是如何工作的并行和并发垃圾回收器以了解各种选项。
然后,查看Java SE 6 HotSpot [tm]虚拟机垃圾回收调优文档,该文档扩展了Java SE 6中引入的GC调优概念和技术,这些概念和技术在使用5.0 Java虚拟机调整垃圾收集文档中介绍。
如果您希望减少垃圾回收暂停时间,那么并发收集器可能是正确的选择,因为它在大部分工作期间都是并发执行的(即在应用程序仍在运行时)。但找到最佳设置需要进行分析(考虑测量GC吞吐量、最大和平均暂停时间、完整GC的频率及其持续时间等)。 (编辑:阅读性能专家Kirk Pepperdine的关于JVM堆调优的建议,请勿触碰旋钮!可能是一个好主意。)

谢谢你的回答,但是在分析中你会寻找什么?哪些数据能够指示一个方向比另一个更好? - Yishai
通常来说,我们会关注垃圾回收的吞吐量、最大和平均暂停时间、Full GC 的频率以及它们的持续时间(以找到最佳折衷方案)。但是很难为您提供具体答案 :) - Pascal Thivent

4
垃圾回收调优不仅是一门科学,更是一门艺术,它取决于你的应用及其使用情况。如果标准的停顿式策略让你烦恼,为什么不转换到CMS(并发标记和清除)或新的G1收集器呢?
最好的方法是更改参数并附加分析器以检查应用程序行为。

4
这是相当自动化的,并且对我们很有效:

-server -Xss4096k -Xms12G -Xmx12G -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -verbose:gc -Xmaxf1 -XX:+UseCompressedOops -XX:+DisableExplicitGC -XX:+AggressiveOpts -XX:+ScavengeBeforeFullGC -XX:CMSFullGCsBeforeCompaction=10 -XX:CMSInitiatingOccupancyFraction=80 -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalMode -XX:+CMSIncrementalPacing -XX:+CMSParallelRemarkEnabled -XX:GCTimeRatio=19 -XX:+UseAdaptiveSizePolicy -XX:MaxGCPauseMillis=500 -XX:+PrintGCTaskTimeStamps -XX:+PrintGCApplicationStoppedTime -XX:+PrintHeapAtGC -XX:+PrintTenuringDistribution -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCApplicationConcurrentTime -XX:+PrintTenuringDistribution -Xloggc:gc.log

对于那些不想烦恼于过于复杂的垃圾回收调优的人来说,这很有帮助。另一个提示:调整最大值以适应您的需求,并从最小值开始:“-Xms16m -XX:PermSize=16m”。在应用程序在满负荷下运行后,检查使用的大小,然后调整最小值。还要删除您不需要的日志选项。 - bebbo

2

没有“最佳”选项(如果有的话,那么任何人都会使用它,对吧?),但可能有一种选项适合您的情况。以下是一些提示:

  • 使用最新的虚拟机。随着每个版本的发布,GC代码变得更好。
  • 使用客户端jvm.dll(自Java 1.5以来在中可用)。这应该是默认设置。
  • 在Java中分配和释放对象很便宜。让它们一直存在是昂贵的。

你的意思是保持对象池不如不断创建对象并强制GC清理它们? - tloach
@tloach:是的。在垃圾回收期间,无法访问的对象(即没有指向它们的引用)不会占用任何内存空间。 - Aaron Digulla

0
如果您想要更好的性能,那么就让垃圾回收器少做一些工作。考虑使用对象池而不是不断地创建和丢弃对象,并确保您需要每个创建的对象。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接