我在Yarn上运行Spark。我不理解以下设置之间的区别:spark.yarn.executor.memoryOverhead
和 spark.memory.offHeap.size
。两者都似乎是为Spark执行器分配堆外内存的设置。应该使用哪一个?另外,对于执行器堆外内存的推荐设置是什么?
非常感谢!
我在Yarn上运行Spark。我不理解以下设置之间的区别:spark.yarn.executor.memoryOverhead
和 spark.memory.offHeap.size
。两者都似乎是为Spark执行器分配堆外内存的设置。应该使用哪一个?另外,对于执行器堆外内存的推荐设置是什么?
非常感谢!
TL;DR: 对于Spark 1.x和2.x,总的堆外内存 = spark.executor.memoryOverhead
(其中包括spark.offHeap.size
)
对于Spark 3.x,总的堆外内存 = spark.executor.memoryOverhead
+ spark.offHeap.size
(来源于此页面)
详细解释:
spark.executor.memoryOverhead
由资源管理器(如YARN)使用,而spark.memory.offHeap.size
由Spark核心(内存管理器)使用。这种关系在不同版本中略有不同。
Spark 2.4.5及之前版本:
spark.executor.memoryOverhead
应该包括spark.memory.offHeap.size
。这意味着,如果您指定了offHeap.size
,则需要将此部分手动添加到memoryOverhead
以供YARN使用。如下面代码所示,从YarnAllocator.scala,当YARN请求资源时,它不知道任何有关offHeap.size
的信息:
private[yarn] val resource = Resource.newInstance(
executorMemory + memoryOverhead + pysparkWorkerMemory,
executorCores)
然而,在 Spark 3.0 中行为发生了改变:
spark.executor.memoryOverhead
不再包括 spark.memory.offHeap.size
。在请求资源时,YARN 将为您包含 offHeap.size
。根据新的文档:
注意:附加内存包括 PySpark 执行程序内存(当未配置 spark.executor.pyspark.memory 时)和由同一容器中运行的其他非执行程序进程使用的内存。运行执行程序的容器的最大内存大小由 spark.executor.memoryOverhead、spark.executor.memory、spark.memory.offHeap.size 和 spark.executor.pyspark.memory 的总和确定。
从代码中也可以看出:
private[yarn] val resource: Resource = {
val resource = Resource.newInstance(
executorMemory + executorOffHeapMemory + memoryOverhead + pysparkWorkerMemory, executorCores)
ResourceRequestHelper.setResourceRequests(executorResourceRequests, resource)
logDebug(s"Created resource capability: $resource")
resource
}
了解更多有关此更改的详细信息,请参阅此Pull Request。
至于您的第二个问题,执行器 offheap 内存的推荐设置取决于您的应用程序,并且您需要进行一些测试。我发现这个页面对进一步解释非常有帮助:
Off-heap 内存是减少 GC 暂停的好方法,因为它不在 GC 的范围内。然而,它带来了序列化和反序列化的开销。后者又使得 off-heap 数据有时会被放到堆内存中,从而暴露给 GC。此外,Project Tungsten 带来的新数据格式(字节数组)有助于降低 GC 开销。这两个原因使得 Apache Spark 应用程序中使用 off-heap 内存应该经过认真规划,并进行测试。
顺便提一下,spark.yarn.executor.memoryOverhead
已经弃用,更改为 spark.executor.memoryOverhead
,这适用于 YARN 和 Kubernetes。
spark.yarn.executor.memoryOverhead
用于静态内存管理器。这在旧版Spark(如1.2)中使用。为每个执行器分配的堆外存储器量(以兆字节为单位)。这是用于计算虚拟机开销、interned字符串、其他本地开销等的内存。这往往随着执行器大小增长而增长(通常为6-10%)。
您可以在较旧的Spark文档中找到此信息,例如Spark1.2文档:
https://spark.apache.org/docs/1.2.0/running-on-yarn.html
spark.memory.offHeap.size
在UnifiedMemoryManager中使用,默认情况下自1.6版本后使用。可以用于非堆分配的内存绝对量(以字节为单位)。这个设置不会影响堆内存使用,因此如果您的执行者的总内存消耗必须符合某些硬限制,那么请确保相应地缩小JVM堆大小。当 spark.memory.offHeap.enabled=true 时,必须将其设置为正值。
您可以在最新的Spark文档中找到此信息,例如Spark2.4文档:
https://spark.apache.org/docs/2.4.4/configuration.html