Skip to content

[SPARK-28537][SQL] DebugExec cannot debug broadcast or columnar related queries. - #25274

Closed
sarutak wants to merge 6 commits into
apache:masterfrom
sarutak:fix-debugexec
Closed

[SPARK-28537][SQL] DebugExec cannot debug broadcast or columnar related queries.#25274
sarutak wants to merge 6 commits into
apache:masterfrom
sarutak:fix-debugexec

Conversation

@sarutak

Copy link
Copy Markdown
Member

DebugExec does not implement doExecuteBroadcast and doExecuteColumnar so we can't debug broadcast or columnar related query.

One example for broadcast is here.

val df1 = Seq(1, 2, 3).toDF
val df2 = Seq(1, 2, 3).toDF
val joined = df1.join(df2, df1("value") === df2("value"))
joined.debug()
java.lang.UnsupportedOperationException: Debug does not implement doExecuteBroadcast
...

Another for columnar is here.

val df = Seq(1, 2, 3).toDF
df.persist
df.debug()
java.lang.IllegalStateException: Internal Error class org.apache.spark.sql.execution.debug.package$DebugExec has column support mismatch:
...

How was this patch tested?

Additional test cases in DebuggingSuite.

@SparkQA

Copy link
Copy Markdown

Test build #108253 has finished for PR 25274 at commit 6fd6260.

  • This patch passes all tests.
  • This patch merges cleanly.
  • This patch adds no public classes.

val rightDF = spark.range(10)
val leftDF = spark.range(10)
val joinedDF = leftDF.join(rightDF, leftDF("id") === rightDF("id"))
Try {

@maropumaropuJul 28, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about checking the actual output like this instead of using Try?

 assert(joinedDF.queryExecution.sparkPlan.collect { case _: BroadcastHashJoinExec => true }.nonEmpty)
val output = new java.io.ByteArrayOutputStream()
Console.withOut(output) {
joinedDF.debug()
}
assert(output.toString.contains("BroadcastHashJoin"))

@sarutaksarutakJul 28, 2019

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the comment. I changed test-cases added to compare expected result to actual one using Console.withOut . But I think it's good to still handle exceptions for better error message when test-cases fail.
To do so, it's easy for us to identify which test-case fails (line number appears on the top of error message).

[info] - SPARK-28537: DebugExec cannot debug broadcast or columnar related queries *** FAILED *** (89 milliseconds)
[info] debug() for broadcast failed with exception (DebuggingSuite.scala:76)
[info] org.scalatest.exceptions.TestFailedException:
[info] at org.scalatest.Assertions.newAssertionFailedException(Assertions.scala:528)
[info] at org.scalatest.Assertions.newAssertionFailedException$(Assertions.scala:527)
[info] at org.scalatest.FunSuite.newAssertionFailedException(FunSuite.scala:1560)

@SparkQA

Copy link
Copy Markdown

Test build #108269 has finished for PR 25274 at commit 8ee28f5.

  • This patch passes all tests.
  • This patch merges cleanly.
  • This patch adds no public classes.

subtree.contains("Range") && code.contains("Object[]")})
}

test("SPARK-28537: DebugExec cannot debug broadcast or columnar related queries") {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO this is of improvements for debugging, so we don't need the prefix. cc: @dongjoon-hyun

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

or -> and in the title.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that @sarutak reported this issue as a BUG.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a BUG.

| id LongType: {}
|""".stripMargin))
} catch {
case e: Throwable => fail("debug() for columnar failed with exception", e)

@maropumaropuJul 28, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

case NonFatal(e) =>


val exprId = df.queryExecution.executedPlan.output.head.toString
val output = captured.toString()
assert(output.contains(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For these kinds of tests, substring matching seems to be better than exact matching.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll follow the manner in ExplainSuite.

@maropumaropu left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM except for minor comments.

@SparkQA

Copy link
Copy Markdown

Test build #108316 has finished for PR 25274 at commit 2685272.

  • This patch passes all tests.
  • This patch merges cleanly.
  • This patch adds no public classes.

@maropu

Copy link
Copy Markdown
Member

cc: @dongjoon-hyun

@sarutak

Copy link
Copy Markdown
MemberAuthor

@dongjoon-hyun Do you have any feedbacks?

|== Range (0, 10, step=1, splits=2) ==
|Tuples output: 0
| id LongType: {}""".stripMargin))
} catch {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need this catch? the test would fail anyway

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's for better error message.
With catch, we can identify which assertion fails easily.
But if we split test cases, I think we can remove try/catch

|Tuples output: 0
| id LongType: {}
|""".stripMargin))
} catch {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

case NonFatal(e) => fail("debug() for broadcast failed with exception", e)
}

val df = spark.range(5)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we split this into 2 different tests?

@mgaido91mgaido91 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM apart from few comments


val output = captured.toString()replaceAll ("#\\d+", "#x")
assert(output.contains(
s"""== InMemoryTableScan [id#xL] ==

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:

Suggested change
s"""== InMemoryTableScan [id#xL] ==
"""== InMemoryTableScan [id#xL] ==

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh... I forgot to remove it.

df.debug()
}

val output = captured.toString()replaceAll ("#\\d+", "#x")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:

Suggested change
valoutput= captured.toString()replaceAll("#\\d+", "#x")
valoutput= captured.toString().replaceAll("#\\d+", "#x")

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! What an embarrassing mistake...


test("SPARK-28537: DebugExec cannot debug columnar related queries") {
val df = spark.range(5)
df.persist()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shall we unpersist this?

@SparkQA

Copy link
Copy Markdown

Test build #108624 has finished for PR 25274 at commit ee1c26f.

  • This patch passes all tests.
  • This patch merges cleanly.
  • This patch adds no public classes.

@SparkQA

Copy link
Copy Markdown

Test build #108626 has finished for PR 25274 at commit 46c6598.

  • This patch passes all tests.
  • This patch merges cleanly.
  • This patch adds no public classes.

@maropu

Copy link
Copy Markdown
Member

Thanks! Merged to master.
Thanks all for your work! @sarutak@mgaido91@kiszk

@maropumaropu closed this Aug 5, 2019
@HyukjinKwon

Copy link
Copy Markdown
Member

@HyukjinKwon

Copy link
Copy Markdown
Member

seems 03e3006 was conflicted with this one.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants

@sarutak@SparkQA@maropu@HyukjinKwon@kiszk@mgaido91@dongjoon-hyun