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
对于纱线。从下面的代码中可以看出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之和确定。
并从code你还可以告诉:
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
}
有关此更改的更多详细信息,您可以参考这个请求请求.
对于第二个问题,执行器堆外内存的推荐设置是什么?这取决于您的应用程序,并且您需要一些测试。我发现this页面有助于进一步解释:
堆外内存是减少 GC 暂停的好方法,因为它不在 GC 的范围内。然而,它带来了序列化和反序列化的开销。后者反过来又使得堆外数据有时可以放入堆内存中,从而暴露给 GC。此外,Project Tungsten(字节数组)带来的新数据格式有助于减少 GC 开销。这两个原因使得 Apache Spark 应用程序中堆外内存的使用应该仔细规划,尤其是测试。
BTW, spark.yarn.executor.memoryOverhead
已弃用并更改为spark.executor.memoryOverhead
,这对于 YARN 和 Kubernetes 来说很常见。