调整生产应用程序的垃圾收集

时间:2016-01-20 15:54:22

标签: java garbage-collection

我的任务是调整一个生产应用程序,该应用程序包含一个Spring MVC REST接口,用于从内存缓存后端的Gemfire中提供大型(〜0mb - 100mb)json文档。该应用程序在JDK 1.6上的Tomcat 7内的CentOS服务器上运行。我们意识到应用程序需要调整,因为我们看到频繁停止世界旧代垃圾收集,如果无人看管,最终会导致java.lang.OutOfMemoryError: GC overhead limit exceeded错误。

通过一些试验和错误以及监控,我设法使用以下参数调整应用程序:

-Xms20g 
-Xmx20g 

-XX:PermSize=256m 
-XX:MaxPermSize=256m

-XX:NewSize=8g 
-XX:MaxNewSize=8g

-XX:SurvivorRatio=8
-XX:+DisableExplicitGC
-XX:+UseConcMarkSweepGC 
-XX:+UseParNewGC
-XX:CMSInitiatingOccupancyFraction=70

我现在看到的垃圾收集行为(在大量测试负载下48小时)是伊甸园空间收集大约每10秒发生一次并持续约0.04秒。 48小时后,老一代人根本没有增长,而且那个地区有0个收藏品。

我的问题是,我是否应该关注不收集旧代垃圾?总的来说,这看起来像一个健康的调整?

修改: 对于关心我的GC日志的人,可以在http://filebin.ca/2U8awo1KTS1D/udf-gc.log.0

获取

2 个答案:

答案 0 :(得分:3)

  

我的问题是,我是否应该关注不收集旧代垃圾?

日志看起来很好。鉴于趋势,老一代的入住率增长非常缓慢。因此,它需要几天时间才能完全启动,以便启动并发标记周期。

  

总的来说,这看起来像一个健康的调整?

好像你给它的内存要多得多。

老一代的入住率约为2G / 12G。这意味着您可能会将其缩小到4G,并且在并发周期开始之前仍需要几个小时

在年轻一代中,大多数年轻人只活到1岁(15岁)。这意味着年轻一代也可以在没有过多增加对象促销的情况下缩小

-XX:CMSInitiatingOccupancyFraction=70

应该与XX:+UseCMSInitiatingOccupancyOnly

结合使用

答案 1 :(得分:0)

调整垃圾收集对于通用性能调优没有什么不同 - 在没有任何要求的情况下(至少对于非平凡的应用程序)有效地持续改进。在某些时候,改进对于实际使用案例不再重要。这就是你应该实现目标的原因。

关于GC的目标应该来自通用性能要求。这些反过来通常描述三个维度

  • 延迟。或者更准确地说,应用程序发布的每个服例如 - 99%的login()操作必须在500ms内完成,最坏的情况不能超过2,500ms。
  • 吞吐量。每个时间单位必须完成多少次操作。更难以测量大型单块,但如果运行微服务,您可以表达为每秒处理1,000次登录操作"。
  • 容量。添加更多资源&向外扩展将改善这种情况,但对于实际问题,诸如每月AWS账单之类的事情将在这方面设定限制。

满足这些要求后,您可以开始构建/推导它们,并在必要时进一步优化。我所隶属的公司最近发布了一本关于GC调整的相当全面的手册,因此您可以从手册的GC tuning sections查看更多内容。