Spark 源码调试总结

最近在测试 Spark 2.3 的性能,其中踩的一些坑,调试源码的一些技巧,适当记录一下。本文是个人随笔,也许逻辑不够清晰,内容较多,敬请谅解。

首先 Spark 源码的基本断点调试,包括修改,仍然首推老大翟士丹的blog,其中有一些远程调试的操作。我们对于一个 Spark Application 是可以开启远程调试端口的,方法类似于蓝天的IT生涯里记录的。

对于 Driver 端的代码调试
  • 例如 Spark SQL 的 Analyser 阶段的改进及调试。
  • 直接在 Spark Application 开启远程调试端口,然后在 IntelliJ IDEA 中连接该端口,之后打断点调试就可以了。
对于 Executor 端的代码调试
  • 用于 Executor 执行时报错。
  • 对于 Executor 端的代码进行调试,看起来比较麻烦,直观看起来得知道在哪个 Executor 执行的代码,然后在这个 Executor 开远程调试端口。有没有更简单的办法呢?Local模式!!。Local模式下,执行任务的 Executor 与 Driver 在同一个JVM进程内。
对于 codegen 的代码调试
  • 这次测试 Spark 2.3 发现一个报错:
Caused by: java.lang.ClassFormatError: org/apache/spark/sql/catalyst/expressions/GeneratedClass$GeneratedIteratorForCodegenStage3
    at org.apache.spark.sql.catalyst.expressions.GeneratedClass.generate(Unknown Source)
    at org.apache.spark.sql.execution.WholeStageCodegenExec$$anonfun$10.apply(WholeStageCodegenExec.scala:610)
	at org.apache.spark.sql.execution.WholeStageCodegenExec$$anonfun$10.apply(WholeStageCodegenExec.scala:608)
    at org.apache.spark.rdd.RDD$$anonfun$mapPartitionsWithIndex$1$$anonfun$apply$26.apply(RDD.scala:847)
    at org.apache.spark.rdd.RDD$$anonfun$mapPartitionsWithIndex$1$$anonfun$apply$26.apply(RDD.scala:847)
    at org.apache.spark.rdd.MapPartitionsRDD.compute(MapPartitionsRDD.scala:38)
    at org.apache.spark.rdd.RDD.computeOrReadCheckpoint(RDD.scala:324)
    at org.apache.spark.rdd.RDD.iterator(RDD.scala:288)
    at org.apache.spark.rdd.MapPartitionsRDD.compute(MapPartitionsRDD.scala:38)
    at org.apache.spark.rdd.RDD.computeOrReadCheckpoint(RDD.scala:324)
    at org.apache.spark.rdd.RDD.iterator(RDD.scala:288)
    at org.apache.spark.rdd.MapPartitionsRDD.compute(MapPartitionsRDD.scala:38)
    at org.apache.spark.rdd.RDD.computeOrReadCheckpoint(RDD.scala:324)
    at org.apache.spark.rdd.RDD.iterator(RDD.scala:288)
    at org.apache.spark.scheduler.ResultTask.runTask(ResultTask.scala:87)
    at org.apache.spark.scheduler.Task.run(Task.scala:109)
    at org.apache.spark.executor.Executor$TaskRunner.run(Executor.scala:345)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
  • 看起来是 codegen 生成的代码有问题,对 SQL 进行分析之后看起来是参数过多导致。之后的问题就是如何拿到 codegen 生成的代码。在此记录一下解决方案:
import org.apache.spark.sql.execution.debug._
import java.io._
val mysql = "select * from test" // or other SQL
val codeGenString = codegenString(sql(mysql).queryExecution.executedPlan)
val writer = new PrintWriter(new File("testCodeGen" ))
writer.write(codeGenString)
writer.close()
  • 这样就可以获取 codegen 生成的代码。
  • 最后发现这个是 Spark 2.3 的 bug,很遗憾发现的时候社区已经将这个 bug 修复一个月了,错失成为 Spark Contributor 的机会;右转 JIRA 查看详情。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值