许多短期对象的Java垃圾收集行为

时间:2015-08-05 17:53:30

标签: java scala garbage-collection apache-kafka

我有一个Java进程,它分配了许多非常短暂的对象(使用YourKit测量,平均年龄在10-20毫秒之间),并且很少有持久对象,它的功能是接受TCP消息,以某种方式改变它,并生产给卡夫卡。

大多数对象是由用Scala编写的Kafka生成器创建的,因此使用了大量不可变对象。再次使用YourKit,我测量了来自Kafka的不可变对象的大小约为总数的75%,而来自Kafka的对象数量约为总数的53%。绝大多数这些对象都没有超过20毫秒。

为了优化我的应用程序这个用例,我试图调整垃圾收集器,以便它将短期对象识别为常见用例,并在它到达旧代之前丢弃大多数。这是我到目前为止使用的旋钮:

-verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps \
-XX:+PrintHeapAtGC -XX:+DisableExplicitGC -XX:+PrintTenuringDistribution \
-XX:+UseParallelOldGC -XX:NewRatio=1 \

最重要的标志是-XX:NewRatio-XX:UseParallelOldGC,但我注意到GC模式中有一些奇怪的行为。

这是第一个完整GC之前的堆使用情况的说明: Heap Usage Transient State

以下是稳态堆使用情况的说明:Heap Usage Steady State

正如您所看到的那样,在第一个完整的GC之前,持续时间非常缓慢(我也使用每个gc之后打印的堆信息确认了这一点),但在第一个完整的GC之后,时效开始非常快。

我不明白这个原因,我发现完全没有必要使用完整的GC - 完整的GC几乎可以回收整个堆,因为绝大多数对象已经失去了强大的参考。 / p>

如果在每个GC之后包含堆信息会有所帮助,我会这样做,但是现在,这应该是足够的信息。

如果有人知道为什么会这样,请告诉我。对于这样的应用来说,一小时的完整GC似乎太频繁了。

编辑:

根据要求,这里有一些额外的信息:

  • 我使用的是Java 7,版本1.7.0_51。
  • 我为此进程分配了1 GB的内存,并且已将堆固定为此大小。
  • 在第一个完整GC之前,来自次要GC的一些堆输出:
{Heap before GC invocations=395 (full 0):
 PSYoungGen      total 521728K, used 519744K [0x00000000e0000000, 0x0000000100000000, 0x0000000100000000)
  eden space 518656K, 100% used [0x00000000e0000000,0x00000000ffa80000,0x00000000ffa80000)
  from space 3072K, 35% used [0x00000000ffd00000,0x00000000ffe10000,0x0000000100000000)
  to   space 2560K, 0% used [0x00000000ffa80000,0x00000000ffa80000,0x00000000ffd00000)
 ParOldGen       total 524288K, used 177521K [0x00000000c0000000, 0x00000000e0000000, 0x00000000e0000000)
  object space 524288K, 33% used [0x00000000c0000000,0x00000000cad5c560,0x00000000e0000000)
 PSPermGen       total 33280K, used 33132K [0x00000000bae00000, 0x00000000bce80000, 0x00000000c0000000)
  object space 33280K, 99% used [0x00000000bae00000,0x00000000bce5b3d0,0x00000000bce80000)
35744.334: [GC
Desired survivor size 2621440 bytes, new threshold 1 (max 15)
 [PSYoungGen: 519744K->1184K(521216K)] 697265K->179113K(1045504K), 0.0039310 secs] [Times: user=0.03 sys=0.00, real=0.01 secs]
Heap after GC invocations=395 (full 0):
 PSYoungGen      total 521216K, used 1184K [0x00000000e0000000, 0x0000000100000000, 0x0000000100000000)
  eden space 518656K, 0% used [0x00000000e0000000,0x00000000e0000000,0x00000000ffa80000)
  from space 2560K, 46% used [0x00000000ffa80000,0x00000000ffba8000,0x00000000ffd00000)
  to   space 2560K, 0% used [0x00000000ffd80000,0x00000000ffd80000,0x0000000100000000)
 ParOldGen       total 524288K, used 177929K [0x00000000c0000000, 0x00000000e0000000, 0x00000000e0000000)
  object space 524288K, 33% used [0x00000000c0000000,0x00000000cadc2560,0x00000000e0000000)
 PSPermGen       total 33280K, used 33132K [0x00000000bae00000, 0x00000000bce80000, 0x00000000c0000000)
  object space 33280K, 99% used [0x00000000bae00000,0x00000000bce5b3d0,0x00000000bce80000)
}
  • 第一个完整GC的堆输出:
{Heap before GC invocations=1457 (full 0):
 PSYoungGen      total 521728K, used 520064K [0x00000000e0000000, 0x0000000100000000, 0x0000000100000000)
  eden space 519168K, 100% used [0x00000000e0000000,0x00000000ffb00000,0x00000000ffb00000)
  from space 2560K, 35% used [0x00000000ffd80000,0x00000000ffe60000,0x0000000100000000)
  to   space 2560K, 0% used [0x00000000ffb00000,0x00000000ffb00000,0x00000000ffd80000)
 ParOldGen       total 524288K, used 523194K [0x00000000c0000000, 0x00000000e0000000, 0x00000000e0000000)
  object space 524288K, 99% used [0x00000000c0000000,0x00000000dfeeea68,0x00000000e0000000)
 PSPermGen       total 34304K, used 34213K [0x00000000bae00000, 0x00000000bcf80000, 0x00000000c0000000)
  object space 34304K, 99% used [0x00000000bae00000,0x00000000bcf695e8,0x00000000bcf80000)
99997.829: [GC
Desired survivor size 2621440 bytes, new threshold 1 (max 15)
 [PSYoungGen: 520064K->1600K(521728K)] 1043258K->525386K(1046016K), 0.0072540 secs] [Times: user=0.04 sys=0.01, real=0.01 secs]
Heap after GC invocations=1457 (full 0):
 PSYoungGen      total 521728K, used 1600K [0x00000000e0000000, 0x0000000100000000, 0x0000000100000000)
  eden space 519168K, 0% used [0x00000000e0000000,0x00000000e0000000,0x00000000ffb00000)
  from space 2560K, 62% used [0x00000000ffb00000,0x00000000ffc90000,0x00000000ffd80000)
  to   space 2560K, 0% used [0x00000000ffd80000,0x00000000ffd80000,0x0000000100000000)
 ParOldGen       total 524288K, used 523786K [0x00000000c0000000, 0x00000000e0000000, 0x00000000e0000000)
  object space 524288K, 99% used [0x00000000c0000000,0x00000000dff82a68,0x00000000e0000000)
 PSPermGen       total 34304K, used 34213K [0x00000000bae00000, 0x00000000bcf80000, 0x00000000c0000000)
  object space 34304K, 99% used [0x00000000bae00000,0x00000000bcf695e8,0x00000000bcf80000)
}
{Heap before GC invocations=1458 (full 1):
 PSYoungGen      total 521728K, used 1600K [0x00000000e0000000, 0x0000000100000000, 0x0000000100000000)
  eden space 519168K, 0% used [0x00000000e0000000,0x00000000e0000000,0x00000000ffb00000)
  from space 2560K, 62% used [0x00000000ffb00000,0x00000000ffc90000,0x00000000ffd80000)
  to   space 2560K, 0% used [0x00000000ffd80000,0x00000000ffd80000,0x0000000100000000)
 ParOldGen       total 524288K, used 523786K [0x00000000c0000000, 0x00000000e0000000, 0x00000000e0000000)
  object space 524288K, 99% used [0x00000000c0000000,0x00000000dff82a68,0x00000000e0000000)
 PSPermGen       total 34304K, used 34213K [0x00000000bae00000, 0x00000000bcf80000, 0x00000000c0000000)
  object space 34304K, 99% used [0x00000000bae00000,0x00000000bcf695e8,0x00000000bcf80000)
99997.837: [Full GC [PSYoungGen: 1600K->0K(521728K)] [ParOldGen: 523786K->17123K(524288K)] 525386K->17123K(1046016K) [PSPermGen: 34213K->33877K(68096K)], 0.1576350 secs] [Times: user=0.53 sys=0.03, real=0.16 secs]
Heap after GC invocations=1458 (full 1):
 PSYoungGen      total 521728K, used 0K [0x00000000e0000000, 0x0000000100000000, 0x0000000100000000)
  eden space 519168K, 0% used [0x00000000e0000000,0x00000000e0000000,0x00000000ffb00000)
  from space 2560K, 0% used [0x00000000ffb00000,0x00000000ffb00000,0x00000000ffd80000)
  to   space 2560K, 0% used [0x00000000ffd80000,0x00000000ffd80000,0x0000000100000000)
 ParOldGen       total 524288K, used 17123K [0x00000000c0000000, 0x00000000e0000000, 0x00000000e0000000)
  object space 524288K, 3% used [0x00000000c0000000,0x00000000c10b8fc8,0x00000000e0000000)
 PSPermGen       total 68096K, used 33877K [0x00000000bae00000, 0x00000000bf080000, 0x00000000c0000000)
  object space 68096K, 49% used [0x00000000bae00000,0x00000000bcf156f0,0x00000000bf080000)
}
  • 第一次完整GC发生后,次要集合的堆输出:
 {Heap before GC invocations=1837 (full 9):
  PSYoungGen      total 509440K, used 507104K [0x00000000e0000000, 0x0000000100000000, 0x0000000100000000)
   eden space 494592K, 100% used [0x00000000e0000000,0x00000000fe300000,0x00000000fe300000)
   from space 14848K, 84% used [0x00000000fe300000,0x00000000fef38000,0x00000000ff180000)
   to   space 14848K, 0% used [0x00000000ff180000,0x00000000ff180000,0x0000000100000000)
  ParOldGen       total 524288K, used 342941K [0x00000000c0000000, 0x00000000e0000000, 0x00000000e0000000)
   object space 524288K, 65% used [0x00000000c0000000,0x00000000d4ee7520,0x00000000e0000000)
  PSPermGen       total 54272K, used 33876K [0x00000000bae00000, 0x00000000be300000, 0x00000000c0000000)
   object space 54272K, 62% used [0x00000000bae00000,0x00000000bcf15378,0x00000000be300000)
 133247.303: [GC
 Desired survivor size 15204352 bytes, new threshold 1 (max 15)
  [PSYoungGen: 507104K->13696K(509440K)] 850045K->369421K(1033728K), 0.0318090 secs] [Times: user=0.37 sys=0.01, real=0.03 secs]
 Heap after GC invocations=1837 (full 9):
  PSYoungGen      total 509440K, used 13696K [0x00000000e0000000, 0x0000000100000000, 0x0000000100000000)
   eden space 494592K, 0% used [0x00000000e0000000,0x00000000e0000000,0x00000000fe300000)
   from space 14848K, 92% used [0x00000000ff180000,0x00000000ffee0000,0x0000000100000000)
   to   space 14848K, 0% used [0x00000000fe300000,0x00000000fe300000,0x00000000ff180000)
  ParOldGen       total 524288K, used 355725K [0x00000000c0000000, 0x00000000e0000000, 0x00000000e0000000)
   object space 524288K, 67% used [0x00000000c0000000,0x00000000d5b63520,0x00000000e0000000)
  PSPermGen       total 54272K, used 33876K [0x00000000bae00000, 0x00000000be300000, 0x00000000c0000000)
   object space 54272K, 62% used [0x00000000bae00000,0x00000000bcf15378,0x00000000be300000)
 }
  • 第一个GC之后的完整GC的堆输出:
{Heap before GC invocations=1457 (full 0):
 PSYoungGen      total 521728K, used 520064K [0x00000000e0000000, 0x0000000100000000, 0x0000000100000000)
  eden space 519168K, 100% used [0x00000000e0000000,0x00000000ffb00000,0x00000000ffb00000)
  from space 2560K, 35% used [0x00000000ffd80000,0x00000000ffe60000,0x0000000100000000)
  to   space 2560K, 0% used [0x00000000ffb00000,0x00000000ffb00000,0x00000000ffd80000)
 ParOldGen       total 524288K, used 523194K [0x00000000c0000000, 0x00000000e0000000, 0x00000000e0000000)
  object space 524288K, 99% used [0x00000000c0000000,0x00000000dfeeea68,0x00000000e0000000)
 PSPermGen       total 34304K, used 34213K [0x00000000bae00000, 0x00000000bcf80000, 0x00000000c0000000)
  object space 34304K, 99% used [0x00000000bae00000,0x00000000bcf695e8,0x00000000bcf80000)
99997.829: [GC
Desired survivor size 2621440 bytes, new threshold 1 (max 15)
 [PSYoungGen: 520064K->1600K(521728K)] 1043258K->525386K(1046016K), 0.0072540 secs] [Times: user=0.04 sys=0.01, real=0.01 secs]
Heap after GC invocations=1457 (full 0):
 PSYoungGen      total 521728K, used 1600K [0x00000000e0000000, 0x0000000100000000, 0x0000000100000000)
  eden space 519168K, 0% used [0x00000000e0000000,0x00000000e0000000,0x00000000ffb00000)
  from space 2560K, 62% used [0x00000000ffb00000,0x00000000ffc90000,0x00000000ffd80000)
  to   space 2560K, 0% used [0x00000000ffd80000,0x00000000ffd80000,0x0000000100000000)
 ParOldGen       total 524288K, used 523786K [0x00000000c0000000, 0x00000000e0000000, 0x00000000e0000000)
  object space 524288K, 99% used [0x00000000c0000000,0x00000000dff82a68,0x00000000e0000000)
 PSPermGen       total 34304K, used 34213K [0x00000000bae00000, 0x00000000bcf80000, 0x00000000c0000000)
  object space 34304K, 99% used [0x00000000bae00000,0x00000000bcf695e8,0x00000000bcf80000)
}
{Heap before GC invocations=1458 (full 1):
 PSYoungGen      total 521728K, used 1600K [0x00000000e0000000, 0x0000000100000000, 0x0000000100000000)
  eden space 519168K, 0% used [0x00000000e0000000,0x00000000e0000000,0x00000000ffb00000)
  from space 2560K, 62% used [0x00000000ffb00000,0x00000000ffc90000,0x00000000ffd80000)
  to   space 2560K, 0% used [0x00000000ffd80000,0x00000000ffd80000,0x0000000100000000)
 ParOldGen       total 524288K, used 523786K [0x00000000c0000000, 0x00000000e0000000, 0x00000000e0000000)
  object space 524288K, 99% used [0x00000000c0000000,0x00000000dff82a68,0x00000000e0000000)
 PSPermGen       total 34304K, used 34213K [0x00000000bae00000, 0x00000000bcf80000, 0x00000000c0000000)
  object space 34304K, 99% used [0x00000000bae00000,0x00000000bcf695e8,0x00000000bcf80000)
99997.837: [Full GC [PSYoungGen: 1600K->0K(521728K)] [ParOldGen: 523786K->17123K(524288K)] 525386K->17123K(1046016K) [PSPermGen: 34213K->33877K(68096K)], 0.1576350 secs] [Times: user=0.53 sys=0.03, real=0.16 secs]
Heap after GC invocations=1458 (full 1):
 PSYoungGen      total 521728K, used 0K [0x00000000e0000000, 0x0000000100000000, 0x0000000100000000)
  eden space 519168K, 0% used [0x00000000e0000000,0x00000000e0000000,0x00000000ffb00000)
  from space 2560K, 0% used [0x00000000ffb00000,0x00000000ffb00000,0x00000000ffd80000)
  to   space 2560K, 0% used [0x00000000ffd80000,0x00000000ffd80000,0x0000000100000000)
 ParOldGen       total 524288K, used 17123K [0x00000000c0000000, 0x00000000e0000000, 0x00000000e0000000)
  object space 524288K, 3% used [0x00000000c0000000,0x00000000c10b8fc8,0x00000000e0000000)
 PSPermGen       total 68096K, used 33877K [0x00000000bae00000, 0x00000000bf080000, 0x00000000c0000000)
  object space 68096K, 49% used [0x00000000bae00000,0x00000000bcf156f0,0x00000000bf080000)
}

1 个答案:

答案 0 :(得分:0)

日志中唯一的完整GC [严重的是,如果没有屠宰它就很难发布日志吗?] 需要大约160毫秒,小型GC需要30毫秒或更短时间。

您没有设置任何暂停时间目标。

在完整的GC之间传递一个或多个小时

如果你的印象是完整的GC在某种程度上是邪恶的"并且必须在所有费用下避免,那你就错了。

使用CMS可能会很麻烦,因为使用CMS时,Full GCs是故障模式单线程回退策略,在大堆上可能需要很长时间。

但你在小堆上使用Parallel Old Gen收集器,又名吞吐量收集器,其中一个完整的GC非常快,特别是当大多数旧的gen内容都是垃圾时不需要通过标记扫描算法访问。

考虑到您甚至没有指定暂停时间目标,或者尝试过的CMS向我建议您甚至没有为他们制定明确的目标。

所以这里没有问题。