【问题标题】:how to optimize large short-lived objects in jvm gc如何优化 jvm gc 中的大型短期对象
【发布时间】:2018-01-19 05:48:05
【问题描述】:

我们遇到了一个关于 jvm gc 的问题。我们有一个大型 QPS 应用程序,jvm 堆内存增加得非常快。它会在几秒钟内使用超过 2g 的堆内存,然后 gc 触发每次收集超过 2g 的内存也非常频繁。GC 收集情况如下图。所以这有两个问题

  1. gc 需要一些时间。更重要的是,它很频繁。
  2. 系统将不稳定。

我将问题抽象为下面的代码。系统快速分配短期对象。

public static void fun1() {
    for(int i = 0; i < 5000; i++) {
        Byte[] bs = new Byte[1024 * 1024 * 5];
        bs = null;
    }
}

所以,我有一些问题:

  1. 很多人说set object equals null会让gc线程收集起来很容易。这是什么意思?我们都知道,当 JVM 无法为新对象分配空间时,总会触发 Minor GC。因此,一个对象是否
    为null,只有在空间不够时才会触发gc。所以 set object is null 没有意义。
  2. 如果存在大型短期对象,如何优化?我的意思是当年轻代不够时如何收集这些对象。

任何建议都会对我有所帮助。

【问题讨论】:

  • 将局部变量设置为null 确实很少有任何效果。此外,我不明白你的实际问题,也不知道你有什么样的解决方案。一个 gc 周期的成本取决于幸存者对象的数量,因此如果在一个 gc 周期内回收了所有 2GiB 对象,则不会那么昂贵。您可以尝试使用Garbage-First Collector 平滑曲线,但更平滑的曲线并不意味着更高的性能...

标签: java memory-leaks garbage-collection jvm


【解决方案1】:

我会说你需要缓存它们。不要每次都重新创建它们,而是尝试找到一种方法来重用已经创建的那些。 尝试使用选项为您的应用分配更多内存

-Xms8g -Xmx8g

gc 是在内存不足时调用的,所以如果你有更多的 gc 就不会那么频繁地调用。

如果没有巨大的物体性质,很难提出有价值的建议。尝试添加此类对象的示例以及如何创建/调用它们。

如果短期对象中有大字节数组,请尝试将它们放在 java 之外(例如,在文件中并仅保留文件路径)。

【讨论】:

    【解决方案2】:

    很多人说 set object equals null 会让 gc 线程收集起来很容易

    关于堆栈溢出的其他几个问题已经涵盖了这个问题,所以我不会在这里重复这些问题。例如。 Is unused object available for garbage collection when it's still visible in stack?

    如果存在大型短期对象,如何优化?我的意思是当年轻一代不够时如何收集这些对象。

    增加年轻代的大小。这样它就可以包含对象。或者使用 G1GC,它可以选择性地收集包含此类对象的区域,而不是整个老年代。

    您也可以尝试使用direct byte buffers,它将在堆外分配内存,从而减少 GC 压力。但是内存将一直分配,直到指向内存的缓冲区被收集。

    除此之外,您应该重新设计代码以避免如此频繁的大量分配。通常可以使用对象池或线程局部变量作为暂存内存。

    【讨论】:

    • 如果使用 G1GC,则 Byte[] bs = new Byte[1024 * 1024 * 5];。这可能会超出默认的G1HeapRegionSize,默认区域大小为最接近 xmx/2048 的 2^n,但必须 >=1M 和 Humongous Allocation。请务必将-XX:G1HeapRegionSize=Xm 更改为比数组分配需要大两倍。此外,在我的测试中,G1GC 在内存消耗量大的场景中不如 SurvivorRatio 小的 ParNewGC 有效。
    猜你喜欢
    • 2012-02-03
    • 2013-10-14
    • 1970-01-01
    • 2020-04-30
    • 2012-04-06
    • 2019-08-23
    • 2018-12-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多