Java垃圾收集器时间限制

时间:2018-02-26 13:18:53

标签: java garbage-collection jvm

情况

我正在为Java竞赛开发一个客户端,每当我收到请求时,我都会有两秒钟的回复。响应之后的时间,直到下一个请求未知。

有时,找到正确的响应需要将近2秒,有时它只需要几毫秒。问题是当垃圾收集发生在其中一个较长的计算中(也会分配很多对象)时,直到两秒结束,因此响应发送得太晚而且我被取消资格。

使用详细的gc输出我发现gc通常需要大约0.6秒,即使我试图将其限制在较低的范围内。我还尝试在较短的计算上调用System.gc()(因为我确信我有大约1.8s,我不需要做任何事情),但它需要1-3s,这也不安全。

我的程序只有很少的长寿命物体,大部分时间都短于一秒钟。

功能

我知道程序将始终在具有这些可用资源的同一台计算机上运行:

我目前的jvm参数:

java -Dfile.encoding=UTF-8 \
  -XX:MaxGCPauseMillis=200 \
  -XX:GCPauseIntervalMillis=2050 \
  -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled \
  -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70 \
  -XX:+ScavengeBeforeFullGC -XX:+CMSScavengeBeforeRemark \
  -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps

  • 我可以告诉gc它现在应该收集一些垃圾,但只能持续约1.5秒吗?
  • 是否有System.gc()等效物仅适用于年轻物体并且不会检查终身代?
  • 可以优化jvm参数以获得更好的结果吗?

1 个答案:

答案 0 :(得分:0)

经过大量的实验,我找到了我需要的旗帜,现在想分享这些知识:

  • -XX:+UseConcMarkSweepGC - 在比较我的用例的G1和CMS的日志结果后,我确定CMS暂停时间较短,此外它仍然支持单线程集合
  • -XX:+ExplicitGCInvokesConcurrent在调用System.gc()时,不会调用Full GC,而是调用标准版。
  • -XX:NewRatio=1老一代与年轻一代的比例,这是我生命对象很少的最低值
  • -mx800m -ms800m减少并修复了内存大小,因此集合将更频繁地发生并花费更少的时间。交易吞吐量以获得响应。
  • -XX:-UseParNewGC禁用收集年轻代的并行化。这是一个交易破坏者,并将GC停止世界时间从0.2-0.5s减少到0.02-0.2s,因为我只有一个核心可用。 (将其与CMS结合使用已弃用,并且可能会在较新的Java版本中删除)

使用这些参数,我可以减少GC暂停时间,从0.4s到3s之间变化,一直小于0.2秒。为了完整起见,这些标志对于调试最有用:

-XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC -XX:+PrintTenuringDistribution

请不要忘记,这些都针对非常具体的要求进行了优化:Onle one core available,很多年轻垃圾,没有旧系列,非常低的世界停留

这是我可以推荐进一步阅读的一个小备忘单:http://blog.ragozin.info/2016/10/hotspot-jvm-garbage-collection-options.html