【发布时间】:2019-11-19 00:03:06
【问题描述】:
我需要澄清一下次要 gc 集合的行为方式。调用a() 或调用b() 在一个长期存在的应用程序中,如果它们在旧空间变大时表现得最差
//an example instance lives all application life cycle 24x7
public class Example {
private Object longLived = new Object();
public void a(){
var shortLived = new ShortLivedObject(longLived); // longLived now is attribute
shortLived.doSomething();
}
public void b(){
new ShortLivedObject().doSomething(new Object()); // actually now is shortlived
}
}
我的疑惑从何而来?我发现在使用的永久空间变大的应用程序中,次要 gc 暂停会增加。
做了一些测试,我发现如果我强制 jvm 使用选项a() 和另一个 jvm 使用选项 b(),那么当旧空间变大时,带有选项 b() 的 jvm 具有更短的暂停持续时间但我不知道为什么。
我在应用程序中解决了这个问题,在 4096 中使用此属性 XX:ParGCCardsPerStrideChunk,但我想知道我上面描述的情况是否会导致 gctimes 增加导致 gccard 表中的扫描速度较慢或者我不知道或根本不相关的东西。
【问题讨论】:
-
一般来说,你不应该期望它们完全不同。
-
@LouisWasserman 当旧空间变大时会发生这种情况,但也许你是对的,这个例子与实际发生的事情无关,我正在寻找一些澄清。我注意到时间响应的百分位 99 和 p99.9 的差异
-
这里的最大问题是您使用的是已弃用的 GC 收集器 -
CMS。你需要切换到G1(或者更好的Shenandoah)看看那里会发生什么。第二个问题是,我怀疑您是否知道LongLivedObject实际上 是一个 long 存活对象——它是否被 GC 根引用?第三,您经常混淆术语:CMS对 young 一代有一个 STW 停顿,在老一代有两个短暂停顿,还有很多其他你混淆的东西。 -
您还提出了 4 个不同的问题,我可以在这里数一数,所有这些问题都非常笼统 - 因此您最好的机会是获得通用答案。
-
@Eugene 我知道这是一个长寿对象。我没有混淆,我总是专注于 ParNew 的小 gc。 .我不是在寻找标志,我只是想了解使用选项
b()是否比使用a()更高效。也许我不清楚,我必须改进问题
标签: java java-8 garbage-collection jvm concurrent-mark-sweep