如何知道从UI的Stage DAG导致OutOfMemory的代码行?

时间:2017-05-07 07:40:03

标签: apache-spark out-of-memory apache-spark-sql

我正在尝试分析我的火花作业中出现OutOfMemory错误失败的问题。

我试图通过查看Spark ApplicationMaster的UI来分析问题。用户界面显示了作业的舞台和任务细分,我将我的分析重点放在遇到任务失败的舞台上。

Stage UI有一个DAG,显示在该阶段执行的实际命令/方法。

问题在于,我有150行代码进行DataFrame转换,最后只有一行执行操作 - 保存到镶木地板。 这意味着所有“蓝色框”都具有最后一行的行号。

是的,他们有一些关于方法的信息(窗口,顺序等),但我在整个代码中都有这些方法,所以我无法知道它所指的是哪一行。

如何找到代码的哪个部分遇到麻烦?

2 个答案:

答案 0 :(得分:3)

由于您不知道哪个转换导致了问题,我建议在转换之间注入操作,以查看哪个操作将重新创建问题。

这是一个小实用功能,我用它来简化: (我称之为<enabled>false</enabled>,因为它打破了DAG)

break

和这段代码:

implicit class ExtendedDataFrame(val df : DataFrame) extends AnyVal {   
    def break(name: String = ""):DataFrame = {
      if (name.nonEmpty) {
        println(s"About to break DAG for $name")
      }

      val cached = df.cache()
      cached.count
      cached
    }
}

将如下所示:

df
    .map(...)
    .map(...)
    .map(...)
    .map(...)
    .action

现在,当您的代码失败时,您将在spark UI中看到确切的行,并且在日志中您将看到在失败之前将要发生的转换。

答案 1 :(得分:2)

我也会检查查询的物理计划,也可能是RDD血统。

使用explain了解实际计划(或df.queryExecution.sparkPlan)以及将要执行的内容。

RDD沿袭可以使用RDD.toDebugString(您可以使用df.rdd访问),它将显示阶段和分区(=任务)。

有了这个,我注册SparkListener并开始收听SparkListenerStageSubmittedSparkListenerStageCompleted个事件。聆听SparkListenerTaskStartSparkListenerTaskEnd也很有帮助。

所有这些都能让你很好地了解什么时候完成或不完成。没有代码审查,更改,重新编译或类似。很干净。

使用SparkListener Spark属性:

可以注册自定义spark.extraListeners
  

应注册的Spark侦听器的完全限定类名的逗号分隔列表(初始化SparkContext时)。

请参阅Spark Listeners — Intercepting Events from Spark Scheduler