5

我将首先给出我们创建的对象的一些细节。并会问一个问题(最后)。

我在 linux 上使用 64 位但 JVM。

我的 jvm 选项是: -Xmx6g -Xms3g -XX:MaxPermSize=256m

分析器 (jprofiler) 指示 2 个位置消耗大量内存: 1) 在这里,每秒创建大约 4 个字符串(每个 110KB),并对每个字符串执行 StringUtils.replace。还执行了一些其他字符串分配等,但分析器清楚地表明 StringUtils.replace 是持有大部分内存的东西。2)在这里,每分钟创建一个包含 4 个对象(单个类)的对象(保留大小,如果 3.5MB),并(重新)放置到静态并发哈希映射中(因此映射在任何时候都只包含 1 个对象)。父对象只有这 4 个子对象,仅此而已。这 4 个对象中的每一个都包含 10K 数组列表、10K 日期和其他字符串等。我明确地将旧的父对象(我从 map.replace() 获得的那个)分配给 null 并明确清除 (ArrayList.clear())数组列表,

内存行为是:内存使用量不断增加,并且在某一时刻主要收集(2GB)发生。次要收集(700MB)也大约每分钟发生一次。

问题:您是否认为#1 实际上导致伊甸园空间已满,因此 JVM 将 #2 中的对象推送到永久空间,因此内存使用量不断增加,直到发生重大收集?出于诊断目的,我将 #2 中的父对象更改为保留 500KB 的大小(小 7 倍,还有 1.4K 的 Date、ArrayList 等实例),我仍然看到相同的内存行为。

我将选项更改为 -Xmx12g -Xms3g -XX:MaxPermSize=256m -XX:NewSize=8g 现在,我看到内存中 #2 中的对象数量较少,我看到任期空间/旧代的增长较慢。#2 中的那些对象现在被快速收集很好,但是 CPU 使用率非常高,因为现在的次要收集非常大(8G)并且每 2 分钟发生一次。

我的目标是快速收集所有对象(所以我看不到内存使用量不断增加),但不要让次要集合太大。

关于我应该采取什么方法的任何建议?

4

1 回答 1

3

收集 eden 空间的成本与 eden 空间中保留的对象数量成正比。由于成本很高,这表明大部分对象的保留时间超过 2 分钟。

由于您每两分钟创建大约 6 GB 的对象(NewSize 包括两个幸存者空间),或者每分钟大约 3 GB,其中大部分来自您建议的大小仅为每分钟几 MB。

我认为更好地了解 3 GB 的来源并减少它会很有用,因为您似乎只需要每分钟保持 10 MB 左右。

顺便说一句:如果您每分钟创建 10 MB 的垃圾,那么您在十小时内只会创建 6 GB,并且在那段时间内您不需要任何次要或主要收集。

如果我跑

public class GCLikeMad {
    public static void main(String... args) {
        for(Long l = 0L; l < Integer.MAX_VALUE * 10L; l++);
    }
}

-XX:NewSize=256m我看到了

[GC 295664K->240K(2121792K), 0.0011190 secs]
[GC 286832K->240K(2113216K), 0.0011510 secs]
[GC 278384K->240K(2105216K), 0.0012900 secs]
[GC 270256K->240K(2097280K), 0.0010110 secs]
[GC 262448K->240K(2257280K), 0.0013450 secs]

-XX:newSize=8g -verbosegc我看到了

[GC 6291664K->320K(7345408K), 0.0017790 secs]
[GC 6291776K->272K(7345408K), 0.0021570 secs]
[GC 6291728K->272K(7345408K), 0.0014490 secs]
[GC 6291728K->240K(8393600K), 0.0016680 secs]
[GC 8388080K->208K(8393600K), 0.0018730 secs]

-XX:NewSize=30g -mx31g -XX:SurvivorRatio=100 -verbosegc此时 32 位引用和仅使用一个 NUMA 内存区域。

[GC 30840864K->256K(31154304K), 0.0014270 secs]
[GC 30840832K->256K(31154304K), 0.0014730 secs]
[GC 30840832K->224K(31154304K), 0.0016500 secs]
[GC 30840800K->272K(31154304K), 0.0015740 secs]
[GC 30840848K->272K(31462336K), 0.0015280 secs]

它开始-XX:NewSize=128g -mx130g -XX:SurvivorRatio=100 -verbosegc有所作为。注意:此时正在使用多个 NUMA 内存区域和 64 位引用。这是每 2 分钟收集一次。

[GC 131586048K->320K(132907264K), 0.0042360 secs]
[GC 131586368K->1376K(132907264K), 0.0058030 secs]
[GC 131587424K->1440K(132907264K), 0.0034110 secs]

此时它已经创建了 200 亿个 Long 对象,而只有三个集合。

我想说 128 GB 的 Eden 空间是巨大的。:D


我的观点是增加伊甸园的大小并不会单独增加 GC 时间。它增加了保留的对象数量,这增加了所花费的时间。

于 2012-04-11T17:41:27.573 回答