我正在调查Java应用程序中的性能问题。我们已经将其缩小到定期非常昂贵的垃圾收集。该应用程序执行非常频繁的YoungGen垃圾收集(稍微多于每分钟一次),但这些通常低于0.5秒。然而,在某些时候,我们会遇到一两个小时,其中收集时间超过20秒,在某些情况下高达160秒。分析gc日志,除了总时间长之外,在这些情况下似乎有所不同的是在内核模式中花费的时间的很大一部分(sys时间值很大)。
什么原因导致在内核模式下花费时间?服务器运行的是Java 1.6.0_45,其中包含-Xms5704m -Xmx5704m
和-XX:+UseParallelOldGC
。
答案 0 :(得分:2)
如此庞大的堆,预计会有很长的Full GC。你可以尝试使用Concurrent Mark和Sweep,因为你的分配率似乎不是太高(每分钟一次不多)。
见 http://java-is-the-new-c.blogspot.de/2013/07/what-drives-full-gc-duration-its.html
关于ConcMarkAndSweepGC: http://java-is-the-new-c.blogspot.de/2013/07/tuning-and-benchmarking-java-7s-garbage.html
至于问题,什么需要系统时间。在GC期间,可能存在与内核和内核内存系统的交互。
如果sys时间非常长,请确保没有交换到磁盘!由于GC需要定期迭代所有已分配的对象,因此物理内存短缺是不可取的,因此如果内存区域被交换到磁盘,GC暂停可能会进入分钟。最好是关闭交换。
答案 1 :(得分:0)
这取决于你们老一代的情况。并行GC不适合5gb堆。如果你检查visualGC,你可能会有大约1.5GB的年轻空间,大约500mbsw的幸存者和大约3.2gb的旧空间。
清除3.2 gb内存确实需要时间。根据您在应用程序中使用的长寿命对象的类型,这次可能会很高。使用可以同时标记和扫描的CMS收集器。这将有助于您的应用程序。如果可能,请使用CMS colelctor -XX的这些设置:-UseAdaptiveSizePolicy -XX:+ UseTLAB -XX:ConcGCThreads = 12
这些shoudl会为你的应用提供一个很好的推动,虽然GC时间现在不会有多大意义,因为停止世界清理会更少。