Java垃圾收集器导致性能不佳?需要建议

时间:2016-05-19 07:35:46

标签: java performance garbage-collection heap-memory

我将简要介绍一下这个问题。我在供应链领域工作,处理物品/产品和SKU。

说,我的整个问题集是100万SKU,我正在运行算法。 现在,我的JVM堆大小为4 GB。

我不能一次处理所有SKU,因为我需要更多的内存。 因此,我将问题集分成较小的批次。每个批次都将包含所有需要一起处理的相关SKU。

现在,我运行了几次迭代来处理整个数据集。比如,如果每批保持约。 5000 SKU,我将有200次迭代/循环。在批次完成处理之前,需要5000 SKU的所有数据。但是当下一批开始时,之前的批次是批量数据不是必需的,因此可以进行垃圾收集。

这是问题背景。现在,由于GC而遇到了特定的性能问题 - 每批需要大约2-3秒才能完成。现在,在这段时间内,GC无法释放任何对象,因为在处理特定批次之前需要所有数据。因此,GC正在将所有这些对象移动到旧Gen(如果我查看yourkit profiler,则有在新的Gen中几乎没有任何东西。因此,旧的增长速度更快,需要完整的GC,这使得我的程序非常慢。有没有办法在这种情况下调整GC,或者可能更改我的代码以不同的方式进行内存分配?

PS - 如果每批次都非常小,我都不会看到这个问题。我相信这是因为GC可以快速释放对象,因为批处理完成得更快,因此不需要移动旧代中的对象。

5 个答案:

答案 0 :(得分:3)

First Google hit表示您可以使用dplyr设置相对于旧代的较大的新生成大小。

答案 1 :(得分:1)

您需要调整-XX:NewRatio,如其他答案中所述。

您可以从设置 -XX:NewRatio = 1 开始,这意味着您的Old gen和young gen会平均分配可用的堆内存。

有关此标志如何与其他内存调整标志一起使用的更多详细信息:https://docs.oracle.com/cd/E19900-01/819-4742/abeik/index.html

答案 2 :(得分:1)

考虑使用object pool pattern

即。创建5000 SKU的拉力,然后为每个批次用新数据初始化每个对象。 通过这种方式,您不会遇到任何GC问题,因为拉力就是您需要分配的所有内容。

答案 3 :(得分:0)

很少提示:

  1. 使用visualvmMAT
  2. 等分析工具检查内存泄漏情况
  3. 如果您没有内存泄漏,请检查当前内存是否足够。如果没有,请分配足够的内存。
  4. 从问题陈述中,oldGen正在增长,导致FullGC。你没有引用你正在使用的垃圾收集器。由于您使用的内存> = 4GB,您应该尝试G1GC alrogithm。在G1GC中,除了配置pause time goal, region size, parallel gc threads etc等关键参数外,您可以保留大部分默认值。
  5. 有关详细信息,请参阅此SE问题:

    Java 7 (JDK 7) garbage collection and documentation on G1

答案 4 :(得分:0)

我知道这有点晚了但仍然......

我使用JVM GC选项玩了很多,这在一定程度上有所帮助。好的是我在这个过程中学到了很多关于GC的知识:)

最后,我做了某种对象池。 由于作业是分批处理的,并且每个批次的大小大致相同并且使用相同数量的对象,因此我创建了一个对象池,每个批次都回收这些对象,而不是每批创建和销毁对象。 在每批次结束时,我只是重置对象(数组为-1等)。 在下一批的开始,我通过重新初始化它们来重用这些对象。另外,对于多线程情况,这些池被设置为ThreadLocals以避免同步开销。