首页 > 解决方案 > JVM - 为什么 YoungGen 在 gc 之间使用堆减少?

问题描述

下面是一些 apache Spark 执行器的 GCViewer 图:

  1. 老一代使用的堆
  2. 年轻代使用堆
  3. GC时间
  4. 有问题的现象

我试图理解(4)中的斜率。为什么 gc 会在整个年轻代堆被使用之前启动(就像之前的 gcs 阶段一样)?为什么它会在回升之前保持单调下降约 5 分钟?例如,我认为如果分配了一个非常大的对象(例如,从 io 套接字读取),就会发生这种情况。但这可能是错误的,因为在那之后老一代没有改变。我并不特别关心这个例子,而只是为了了解更多关于 jvm 内存管理的知识。

在此处输入图像描述

标签: javaapache-sparkmemory-managementgarbage-collectionjvm

解决方案


我能想到的一种可能的解释是线程局部分配块(TLAB)的结果。为了避免多个线程使用指向 Eden 空间的单个指针的争用,每个应用程序线程都有自己的指向 Eden 空间中的内存块的指针。当一个 TLAB 用完时,分配一个新的(这也可能涉及分配一个更大的块,以便可以消除线程分配率之间的差异)。

这意味着当需要发生 GC 时,TLAB 中通常会有未使用的空间(因为一个线程需要一个新的 TLAB 并且没有足够的空间供它使用)。您可能会遇到一种情况,即 TLAB 中剩余的空间量由于其他线程的分配率而增加。

由于这是整个年轻代,因此在幸存者空间中也有可能存在对象正在以一种会导致使用的空间量像这样下降的速度获得终身。

不幸的是,从提供的数据来看,无法给出明确的答案。


推荐阅读