是否有人在Java中使用12 GB或更高的超大堆有经验?
- GC是否会使程序无法使用?
- 您使用什么GC参数?
- 哪种JVM,Sun或BEA更适合于此?
- 在这种情况下,哪种平台(Linux或Windows)性能更好?
- 在Windows的情况下,如此高的内存负载下64位Vista和XP之间会有性能差异吗?
Answers:
如果您的应用程序不是交互式的,并且GC暂停对您来说不是问题,那么64位Java处理非常大的堆(即使在数百GB中)也不应该有任何问题。我们也没有在Windows或Linux上发现任何稳定性问题。
但是,当您需要将GC暂停时间保持在较低水平时,情况会变得非常令人讨厌:
忘记默认的吞吐量,请停下世界。对于中等大小的堆(<〜30 GB),它将使您的应用程序暂停数十秒,对于较大的堆(>〜30 GB),它将使应用程序暂停数分钟。而且,购买更快的DIMM将无济于事。
最好的选择可能是由-XX:+ UseConcMarkSweepGC启用的CMS收集器。CMS垃圾收集器仅在初始标记阶段和标记阶段停止应用程序。对于小于4 GB的非常小的堆,这通常不是问题,但是对于创建大量垃圾和大堆的应用程序,标记阶段可能需要很长时间-通常比完全停止运行要少得多。 ,但对于很大的堆仍然可能是个问题。
如果CMS垃圾收集器的速度不够快,无法在长期使用的垃圾填满之前完成操作,它将退回到标准的世界各地GC。对于大小为16 GB的堆,可能需要30秒或更长时间的长时间停顿。您可以尝试避免这种情况,以使应用程序的长寿命垃圾产生率尽可能低。请注意,运行应用程序的核心数量越多,解决此问题的可能性就越大,因为CMS仅利用一个核心。显然,请注意,不能保证CMS不会退回到STW收集器。而且,当发生这种情况时,通常会在峰值负载时发生,并且您的应用程序将停止运行几秒钟。您可能不想为这种配置签署SLA。
好吧,那是G1的新事物。从理论上讲,它是为避免CMS问题而设计的,但我们已经尝试过并观察到:
如果您有能力购买一台具有大内存的大型服务器,那么您也可能会为一项出色的,商业硬件加速的,不间断的GC技术付出高昂的代价,例如Azul提供的那种技术。我们有一台服务器具有384 GB的RAM,它的确运行良好-没有暂停,GC中的零行代码停止运行。
编写应用程序该死的部分,该部分需要使用C ++进行大量存储,就像LinkedIn在社交图处理中所做的那样。您仍然不能通过这样做避免所有问题(例如,堆碎片),但是将暂停时间保持在较低水平肯定会更容易。
我是Azul Systems的首席执行官,因此我对这个主题的看法显然带有偏见!:) 话虽如此...
Azul的CTO Gil Tene很好地概述了与垃圾回收相关的问题,并在他的《理解Java垃圾回收以及您可以对此做些什么》演示文稿中对各种解决方案进行了回顾,并且本文还提供了其他详细信息:http:// www.infoq.com/articles/azul_gc_in_detail。
我们的Zing JVM中的Azul的C4垃圾收集器既是并行的又是并发的,并且对于新世代和旧世代都使用相同的GC机制,在这两种情况下并发工作和压缩。最重要的是,C4没有世界末日的回落。所有压缩都与正在运行的应用程序同时执行。我们的客户运行很大(数百GB),而更糟糕的情况是GC暂停时间小于10毫秒,并且取决于应用程序的时间通常少于1-2毫秒。
CMS和G1的问题在于,必须在某个时刻压缩Java堆内存,并且这两个垃圾收集器都会停止运行世界/ STW(即暂停应用程序)以执行压缩。因此,尽管CMS和G1可以推出STW暂停,但它们并不能消除它们。但是,Azul的C4确实可以完全消除STW暂停,这就是Zing即使对于巨大的堆大小也具有如此低的GC暂停的原因。
我们有一个为12-16 Gb分配应用程序的应用程序,但实际上在正常运行期间只能达到8-10 Gb。我们使用Sun JVM(尝试过IBM,这虽然有点麻烦,但是那可能只是我们的无知...我发誓要在IBM工作的朋友)。只要给应用程序提供喘息的空间,JVM就可以在没有太多GC的情况下处理大型堆。大量的“额外”记忆是关键。
Linux几乎总是比Windows更稳定,当它不稳定时,弄清楚为什么会很容易。Solaris也是坚如磐石,您也可以获得DTrace :)有了这些负载,为什么您要使用Vista或XP?您只是在自找麻烦。我们对GC参数没有任何幻想。我们确实将最小分配设置为等于最大分配,因此它不是一直在尝试调整大小,而是这样。
我已经在Linux和Solaris的两个不同应用程序上分别使用了超过60 GB的堆大小,分别使用了Sun 1.6 JVM的64位版本。
基于Linux的应用程序我从未遇到过垃圾回收问题,除非将其推到堆大小限制附近。为了避免这种情况所固有的严重问题(花太多时间进行垃圾收集),我只是优化了整个程序的内存使用率,以使峰值使用率比64 GB的堆大小限制小5-10%。
但是,在Solaris下运行其他应用程序的情况下,我遇到了严重的垃圾回收问题,因此有必要进行大量调整。这主要包括三个步骤:
通过-XX:+ UseParallelGC -XX:+ UseParallelOldGC JVM选项启用/强制使用并行垃圾收集器,以及通过-XX:ParallelGCThreads选项控制使用的GC线程数。有关更多详细信息,请参见“ Java SE 6 HotSpot虚拟机垃圾收集优化”。
不再需要将局部变量设置为“ null”时,将它们设置得过于广泛而且看似荒谬。这些变量中的大多数是超出范围后应符合垃圾回收条件的变量,它们不是内存泄漏情况,因为未复制引用。但是,出于某种原因,出于某种原因,在涉及的Solaris平台下,出于某种原因,这种“垃圾处理”策略有助于垃圾回收。
长时间分配临时对象后,有选择地在关键代码部分使用System.gc()方法调用。我知道反对使用这些调用的标准警告,以及它们通常通常是不必要的说法,但是我发现在运行此内存密集型应用程序时,它们对于驯服垃圾回收至关重要。
上面的三个步骤使保持该应用程序的运行状态和在大约60 GB的堆使用量下高效运行成为可能,而不是超出控制范围而扩大到适当的128 GB堆大小限制。特别是并行垃圾收集器非常有用,因为当有许多对象时,大型垃圾收集周期非常昂贵,也就是说,大型垃圾收集所需的时间取决于堆中对象的数量。
我无法对这种规模的其他特定于平台的问题发表评论,也无法使用非Sun(Oracle)JVM。
我建议还考虑进行堆转储,看看可以在应用程序中改善内存使用的地方,并通过诸如Eclipse的MAT之类的方法来分析转储。MAT页面上有一些文章,介绍如何开始寻找内存泄漏。您可以使用jmap来获取转储,例如...
jmap -heap:format=b pid
如上所述,如果您有一个非交互式程序,则默认的(压缩)垃圾收集器(GC)应该可以正常工作。如果您有一个交互式程序,并且(1)分配内存的速度不超过GC可以保持的速度,并且(2)不要创建太大(相对于总数)的临时对象(或对象集合) GC所需的最大JVM内存),则CMS适合您。
如果您有一个交互式程序,GC的呼吸空间不足,就会遇到麻烦。不管您有多少内存,这都是事实,但是内存越多,性能越差。这是因为当内存不足时,CMS将耗尽内存,而压缩GC(包括G1)将暂停所有操作,直到检查完所有内存是否存在垃圾为止。停下来的停顿变得更大,您拥有更多的内存。相信我,您不希望servlet暂停一分钟以上。我针对G1中的这些停顿写了详细的StackOverflow答案。
从那以后,我的公司改用了Azul Zing。它仍然无法解决您的应用确实需要更多内存的情况,但是直到那一刻它仍然像梦一样运行。
但是,当然,Zing不是免费的,其特殊的调味料已获得专利。如果您的时间远远超过金钱,请尝试重写您的应用程序以使用JVM集群。
在不久的将来,Oracle正在开发用于千兆字节堆的高性能GC。但是,到目前为止,这不是一个选择。
您应该尝试对您的应用程序运行visualgc。它是堆可视化工具,是jvmstat的一部分,可从http://java.sun.com/performance/jvmstat/下载。
这比读取GC日志容易得多。
它可以快速帮助您了解堆的各个部分(各代)的工作方式。虽然您的总堆可能是10GB,但堆的各个部分会小得多。堆的Eden部分中的GC相对便宜,而旧一代中的完整GC则很昂贵。调整堆大小,以使伊甸园很大,几乎不碰老一辈是一个好策略。这可能会导致很大的整体堆,但是如果JVM从未触及页面,那将是一个虚拟页面,而不必占用RAM。
几年前,我比较了JRockit和Sun JVM的12G堆。JRockit胜出,Linux大页面支持使我们的测试运行速度提高了20%。作为我们的测试,YMMV非常占用处理器/内存,并且主要是单线程的。
这是来自Java冠军之一的gc文章-http: //kirk.blog-city.com/is_your_concurrent_collector_failing_you.htm
柯克,作者写道:“向我发送您的GC日志
我目前对研究Sun JVM生产的GC日志感兴趣。由于这些日志不包含任何业务相关信息,因此应该很轻松地保护专有信息。我只想在日志中提到操作系统,JRE的完整版本信息,以及您设置的所有与桩/ gc相关的命令行开关。我还想知道您是否正在运行Grails / Groovey,JRuby,Scala或Java以外的其他程序。最佳设置是-Xloggc:。请注意,此日志在达到操作系统大小限制时不会翻转。如果我发现任何有趣的事情,我将很高兴为您提供一个简短的摘要。”
Sun关于Java 6的文章可以为您提供帮助:https : //www.oracle.com/java/technologies/javase/troubleshooting-javase.html