Spark 驱动程序上的 OutOfMemoryError - 配置 10Gb 时堆转储 1Gb

OutOfMemoryError on Spark's driver - heap dump 1Gb while 10Gb is configured

运行我的 Spark 应用程序时,我有一个 100% 可重现的 OutOfMemoryError(通常是由于超过了 GC 开销限制)。这大约发生在第 700 个阶段。

由于错误堆栈总是包含类,如.ui.TaskSchedulerImpl等,我得出结论问题不在于执行程序,而是在驱动程序进程中 本身。 这个结论得到以下观察结果的支持:在 OOM 之前几分钟,stdout 输出开始暂停一秒钟左右,暂停后立即打印大量行。

spark.driver.memory配置为10G,但是使用的调试工具显示驱动只使用了1Gb:

  1. 我已经使用了这些 great instructions on collecting GC statistics and analyzing it with the gceasy.io 服务;它清楚地表明:
    • GC 后最大堆使用量约为 1Gb。
    • 临近OOM时刻,'heap usage'图几乎触及1Gb的最大值,大量的GC事件未能影响到这一点。 GC overhead limit exceeded 处于最佳状态。
  2. 我使用 MAT 分析了在 OutOfMemoryError 之后立即创建的堆转储。
    • 堆转储包含大约相同的 1Gb 数据。
    • 支配树显示超过一半被 UI 个对象消耗。

的回答表明10Gb-1Gb=9Gb可能被JNI库使用;但显然 Spark 的核心并没有使用它;我也不是。

我已经使用 this question 的答案来最小化保留的 UI 数据。结果,我的申请 运行 成功了。 但我还没有准备好放弃所有可以使用 Spark 探索的宝贵调试数据 UI。

此外,我找不到任何关于 Spark 驱动程序内存模型的解释。

问题是:我如何保留 UI 调试数据而不 运行 我的驱动程序出现 OOM?

实际问题是驱动进程只使用了 1Gb 内存,尽管设置了 spark.driver.memory=10G

根据documentation在客户端模式下,这个配置 (spark.driver.memory) 不能直接通过SparkConf设置您的应用程序,因为此时 JVM 驱动程序已经启动。相反,请通过 --driver-memory 命令行选项或在您的默认属性文件中进行设置。

我用的是客户端模式。将设置从 Spark 上下文参数移动到 spark-submit 命令行参数解决了这个问题。

P.S。 "If nothing works as expected, read the manual" (c).