生产环境中的JavaG1垃圾收集

生产环境中的JavaG1垃圾收集,java,garbage-collection,java-7,g1gc,Java,Garbage Collection,Java 7,G1gc,由于Java7将在默认情况下使用新的G1垃圾收集,Java是否能够处理一个数量级更大的堆,而不需要假定的“破坏性”GC暂停时间?是否有人在生产中实际实施了G1,您的经验是什么 公平地说,我唯一一次看到真正长的GC暂停是在非常大的堆上,比工作站要多得多。澄清我的问题;G1会为数百GB的堆打开网关吗?TB?听起来G1的目的是要有较小的暂停时间,甚至可以指定最大暂停时间目标 垃圾收集不再只是一个简单的“嘿,它满了,让我们一次移动所有东西,然后重新开始”的交易——它是一个极其复杂的、多层次的后台线程系统

由于Java7将在默认情况下使用新的G1垃圾收集,Java是否能够处理一个数量级更大的堆,而不需要假定的“破坏性”GC暂停时间?是否有人在生产中实际实施了G1,您的经验是什么


公平地说,我唯一一次看到真正长的GC暂停是在非常大的堆上,比工作站要多得多。澄清我的问题;G1会为数百GB的堆打开网关吗?TB?

听起来G1的目的是要有较小的暂停时间,甚至可以指定最大暂停时间目标

垃圾收集不再只是一个简单的“嘿,它满了,让我们一次移动所有东西,然后重新开始”的交易——它是一个极其复杂的、多层次的后台线程系统。它可以在后台完成大部分维护工作,而不需要任何暂停,它还可以在运行时使用系统预期模式的知识来提供帮助——比如假设大多数对象在创建后立即死亡,等等

我想说,随着未来的发布,GC暂停时间将继续改善,而不是恶化

编辑:

在重读的过程中,我突然想到我每天都在使用Java——Eclipse、Azureus和我开发的应用程序,我已经很久没有看到停顿了。没有明显的停顿,但我指的是任何停顿

当我右键单击windows资源管理器时,或者(偶尔)连接某些USB硬件时,我看到过暂停,但使用Java时——根本没有


GC仍然是一个问题吗?

G1收集器减少了完整收集的影响。如果您的应用程序已经减少了对完整收集的需求,那么并发地图扫描收集器也同样好,而且根据我的经验,次要收集时间更短

CMS可能会导致性能缓慢下降,即使您在运行它时没有积累长期对象。这是因为G1应该避免内存碎片


关于G1只有付费支持才能使用的神话就是这样,一个神话。Sun和Oracle已经在JDK页面上澄清了这一点。

我一直在用一个繁重的应用程序进行测试:60-70GB分配给堆,20-50GB随时可用。对于这些类型的应用程序,说您的里程数可能有所不同是轻描淡写的。我正在Linux上运行JDK1.6_22。次要版本很重要——在大约1.6_20之前,G1中存在导致随机NullPointerException的bug

我发现它在大多数时候都能很好地保持在你设定的暂停目标之内。默认设置是100毫秒(0.1秒)的暂停,我已经告诉它暂停一半(-XX:MaxGCPauseMillis=50)。然而,一旦它的内存真的很低,它就会惊慌失措,并完全停止世界垃圾收集。对于65GB,这需要30秒到2分钟。(CPU的数量可能没有什么区别;它可能受到总线速度的限制。)

与CMS(不是默认的服务器GC,但应该用于web服务器和其他实时应用程序)相比,典型的暂停更容易预测,并且可以缩短。到目前为止,我有更好的运气与CMS的巨大暂停,但这可能是随机的;我每24小时只见到他们几次。目前我不确定哪一个更适合我的生产环境,但可能是G1。如果甲骨文继续调整它,我怀疑G1最终将是明显的赢家


如果你对现有的垃圾收集器没有问题,现在没有理由考虑G1。如果您正在运行一个低延迟的应用程序,例如GUI应用程序,G1可能是正确的选择,MAXGCPAUSEMILIS设置得非常低。如果您运行的是批处理模式的应用程序,G1不会给您买任何东西。

虽然我还没有在生产中测试G1,但我想我会指出,对于没有“巨大”堆的情况,GCs已经存在问题。具体来说,仅具有2或4个GIG的服务可能会受到GC的严重影响。年轻一代地面军事系统通常没有问题,因为它们以一位数毫秒(或最多两位数)完成。但是,旧一代产品的问题要大得多,因为旧一代产品的大小为1G或以上,它们需要几秒钟的时间

现在:理论上,CMS在这方面可以帮助很多,因为它可以同时运行大部分操作。然而,随着时间的推移,会有一些情况下,它不能做到这一点,必须回落到“停止世界”收集。当这种情况发生时(比如说,一个小时后——不经常,但仍然太经常),那么,抓紧你那该死的帽子。这可能需要一分钟或更长时间。对于试图限制最大延迟的服务来说,这尤其有问题;现在,服务一个请求不再需要25毫秒,而是需要10秒或更长时间。添加伤害来侮辱客户机通常会超时请求并重试,从而导致进一步的问题(也称为“狗屎风暴”)

这是一个G1希望能提供很多帮助的领域。我在一家大公司工作,该公司为存储和消息发送提供云服务;我们不能使用CMS,因为尽管它在很多时候比平行品种更好,但它有这些崩溃。所以大约一个小时,一切都很好;然后东西打到了风扇上。。。由于服务是基于集群的,当一个节点出现故障时,其他节点通常也会出现故障(因为GC导致的超时导致其他节点认为节点崩溃,从而导致重新路由)


我不认为GC对应用程序来说是一个很大的问题,甚至可能非集群服务也很少受到影响。但是越来越多的系统被集群化(特别是由于NoSQL数据存储),堆的大小也在增长。OldGen GC与堆大小呈超线性关系(这意味着堆大小加倍会使GC时间加倍,假设实时数据集的大小也加倍)。

G1使应用程序更加敏捷
-server -Xms512m -Xmx3076m -XX:NewRatio=50 -XX:+HeapDumpOnOutOfMemoryError -XX:+UseG1GC -XX:+AggressiveOpts -XX:+UnlockExperimentalVMOptions -XX:MaxGCPauseMillis=400 -XX:GCPauseIntervalMillis=8000 -XX:+PrintGCTimeStamps -XX:+PrintGCApplicationStoppedTime -XX:+PrintGCApplicationConcurrentTime
-d64 -server -Xss4m -Xms1024m -Xmx4096m -XX:NewRatio=50 -XX:+UseG1GC -XX:+UnlockExperimentalVMOptions -XX:+HeapDumpOnOutOfMemoryError -XX:-DisableExplicitGC -XX:+AggressiveOpts -Xnoclassgc -XX:+UseNUMA -XX:+UseFastAccessorMethods -XX:ReservedCodeCacheSize=48m -XX:+UseStringCache -XX:+UseStringDeduplication -XX:MaxGCPauseMillis=400 -XX:GCPauseIntervalMillis=8000
-XX:G1HeapRegionSize=n, XX:MaxGCPauseMillis=m, -XX:ParallelGCThreads=n, 
-XX:ConcGCThreads=n apart from -Xms and -Xmx