繁体   English   中英

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

[英]Java Garbage Collection Behavior for Many Short-Lived Objects

我有一个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之前的堆使用情况的说明: 堆使用瞬态

以下是稳态堆使用情况的说明: 堆使用稳态

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

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

如果在每个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之后的堆输出:
 {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 [严重的是,如果没有屠宰它就过于难以发布日志吗?]需要大约160毫秒,小的GC需要30毫秒或更短时间。

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

完整的GC之间经过一个小时或更长时间

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

它们对CMS来说很麻烦,因为使用CMS时,Full GCs是一种失败模式的单线程回退策略,在大堆上可能需要很长时间。

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

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

所以这里没有问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM