Spark内存分配比例 vs Java堆中的年轻代/老年代划分

4
我正在学习Spark,对执行器内存的分割有些疑问。具体来说,在Spark Apache文档(这里)中指出:

Java堆空间分为两个区域:年轻代和老年代。年轻代用于保存短生命周期的对象,而老年代则用于保存长生命周期的对象。

这是其中一个例子:

enter image description here

但是对于Spark Executor而言,内存还有另一个抽象的分割,正如Spark Apache文档(此处)所述:

Spark中的内存使用主要可以分为两类:执行和存储。执行内存指用于洗牌、连接、排序和聚合等计算的内存,而存储内存指用于缓存和在集群中传播内部数据的内存。在Spark中,执行和存储共享一个统一的区域(M)。

如下图所示:

enter image description here

我不明白Young Gen和Old Gen如何与存储和执行内存重叠,因为在同一文档中(always here)说明了:

spark.memory.fraction将M的大小表示为(JVM堆空间-300MiB)(默认值0.6)的一部分。其余空间(40%)保留给用户数据结构、Spark内部元数据以及在出现稀疏和异常大记录的情况下防止OOM错误。

其中spark.memory.fraction代表Java Heap的执行\存储内存部分。

但是

如果OldGen接近饱和状态,请通过降低spark.memory.fraction来减少缓存使用的内存量;缓存较少的对象比减慢任务执行更好。

这似乎表明OldGen实际上是用户内存,但以下语句似乎与我的假设相矛盾

如果OldGen接近饱和状态,则可以考虑减小Young generation的大小。

我看漏了什么?

Young Gen和Old Gen的划分与Spark分数和用户内存有什么关系?

1
我不理解Young Gen\Old gen如何与存储\执行内存重叠...这些是堆内存上垃圾回收提供的概念(这些是垃圾内存查找的堆内存部分)...Spark执行器内存(即相同的堆内存)非常简单=应用程序内存+缓存内存。...就像这两个应用程序(Spark和GC)从各自的角度看到了相同的堆内存。 - kavetiraviteja
1个回答

3
简短的回答是,它们除了都与JVM堆有关之外,并没有真正的相关性。
更好的思考方式是将其分为四个桶(编号无意义):
1. 年轻代中的Spark内存 2. 老年代中的Spark内存 3. 年轻代中的用户内存 4. 老年代中的用户内存
(技术上还有一些既不是Spark也不是用户的系统内存,但这通常足够小,不需要担心:这也可以是老的或年轻的。)
一个对象是否被归类为Spark还是用户是由Spark决定的(我实际上不知道这是否是永久的分类,或者对象是否可以在这方面改变其分类)。
至于老 vs 年轻,这由垃圾收集器管理,并且GC可以并且会将对象从年轻代提升到老年代。在某些GC算法中,代的大小会动态调整(或者它们使用固定大小的区域,给定区域可以是老的或年轻的)。
你可以控制1+2、3+4、1+3和2+4的总容量,但你实际上并没有(也可能不想要,因为在一个类别中使用多余空间以暂时获取另一个类别更多空间有很多好处)对1、2、3或4的容量控制。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接