[SPARK-14544] [SQL] improve performance of SQL UI tab
## What changes were proposed in this pull request? This PR improve the performance of SQL UI by: 1) remove the details column in all executions page (the first page in SQL tab). We can check the details by enter the execution page. 2) break-all is super slow in Chrome recently, so switch to break-word. 3) Using "display: none" to hide a block. 4) using one js closure for for all the executions, not one for each. 5) remove the height limitation of details, don't need to scroll it in the tiny window. ## How was this patch tested? Exists tests. ![ui](https://cloud.githubusercontent.com/assets/40902/14445712/68d7b258-0004-11e6-9b48-5d329b05d165.png) Author: Davies Liu <davies@databricks.com> Closes #12311 from davies/ui_perf.
This commit is contained in:
parent
3e53de4bdd
commit
1ef5f8cfa6
|
@ -106,21 +106,22 @@ pre {
|
||||||
line-height: 18px;
|
line-height: 18px;
|
||||||
padding: 6px;
|
padding: 6px;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
word-break: break-word;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stage-details {
|
.stage-details {
|
||||||
max-height: 100px;
|
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
display: block;
|
||||||
transition: max-height 0.25s ease-out, padding 0.25s ease-out;
|
transition: max-height 0.25s ease-out, padding 0.25s ease-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stage-details.collapsed {
|
.stage-details.collapsed {
|
||||||
max-height: 0;
|
|
||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
padding-bottom: 0;
|
padding-bottom: 0;
|
||||||
border: none;
|
border: none;
|
||||||
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.description-input {
|
.description-input {
|
||||||
|
@ -143,14 +144,15 @@ pre {
|
||||||
max-height: 300px;
|
max-height: 300px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
display: block;
|
||||||
transition: max-height 0.25s ease-out, padding 0.25s ease-out;
|
transition: max-height 0.25s ease-out, padding 0.25s ease-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stacktrace-details.collapsed {
|
.stacktrace-details.collapsed {
|
||||||
max-height: 0;
|
|
||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
padding-bottom: 0;
|
padding-bottom: 0;
|
||||||
border: none;
|
border: none;
|
||||||
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
span.expand-additional-metrics, span.expand-dag-viz {
|
span.expand-additional-metrics, span.expand-dag-viz {
|
||||||
|
|
|
@ -55,6 +55,12 @@ private[ui] class AllExecutionsPage(parent: SQLTab) extends WebUIPage("") with L
|
||||||
}
|
}
|
||||||
_content
|
_content
|
||||||
}
|
}
|
||||||
|
content ++=
|
||||||
|
<script>
|
||||||
|
function clickDetail(details) {{
|
||||||
|
details.parentNode.querySelector('.stage-details').classList.toggle('collapsed')
|
||||||
|
}}
|
||||||
|
</script>
|
||||||
UIUtils.headerSparkPage("SQL", content, parent, Some(5000))
|
UIUtils.headerSparkPage("SQL", content, parent, Some(5000))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -118,14 +124,12 @@ private[ui] abstract class ExecutionTable(
|
||||||
{failedJobs}
|
{failedJobs}
|
||||||
</td>
|
</td>
|
||||||
}}
|
}}
|
||||||
{detailCell(executionUIData.physicalPlanDescription)}
|
|
||||||
</tr>
|
</tr>
|
||||||
}
|
}
|
||||||
|
|
||||||
private def descriptionCell(execution: SQLExecutionUIData): Seq[Node] = {
|
private def descriptionCell(execution: SQLExecutionUIData): Seq[Node] = {
|
||||||
val details = if (execution.details.nonEmpty) {
|
val details = if (execution.details.nonEmpty) {
|
||||||
<span onclick="this.parentNode.querySelector('.stage-details').classList.toggle('collapsed')"
|
<span onclick="clickDetail(this)" class="expand-details">
|
||||||
class="expand-details">
|
|
||||||
+details
|
+details
|
||||||
</span> ++
|
</span> ++
|
||||||
<div class="stage-details collapsed">
|
<div class="stage-details collapsed">
|
||||||
|
@ -142,30 +146,6 @@ private[ui] abstract class ExecutionTable(
|
||||||
<div>{desc} {details}</div>
|
<div>{desc} {details}</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
private def detailCell(physicalPlan: String): Seq[Node] = {
|
|
||||||
val isMultiline = physicalPlan.indexOf('\n') >= 0
|
|
||||||
val summary = StringEscapeUtils.escapeHtml4(
|
|
||||||
if (isMultiline) {
|
|
||||||
physicalPlan.substring(0, physicalPlan.indexOf('\n'))
|
|
||||||
} else {
|
|
||||||
physicalPlan
|
|
||||||
})
|
|
||||||
val details = if (isMultiline) {
|
|
||||||
// scalastyle:off
|
|
||||||
<span onclick="this.parentNode.querySelector('.stacktrace-details').classList.toggle('collapsed')"
|
|
||||||
class="expand-details">
|
|
||||||
+details
|
|
||||||
</span> ++
|
|
||||||
<div class="stacktrace-details collapsed">
|
|
||||||
<pre>{physicalPlan}</pre>
|
|
||||||
</div>
|
|
||||||
// scalastyle:on
|
|
||||||
} else {
|
|
||||||
""
|
|
||||||
}
|
|
||||||
<td>{summary}{details}</td>
|
|
||||||
}
|
|
||||||
|
|
||||||
def toNodeSeq: Seq[Node] = {
|
def toNodeSeq: Seq[Node] = {
|
||||||
<div>
|
<div>
|
||||||
<h4>{tableName}</h4>
|
<h4>{tableName}</h4>
|
||||||
|
@ -197,7 +177,7 @@ private[ui] class RunningExecutionTable(
|
||||||
showFailedJobs = true) {
|
showFailedJobs = true) {
|
||||||
|
|
||||||
override protected def header: Seq[String] =
|
override protected def header: Seq[String] =
|
||||||
baseHeader ++ Seq("Running Jobs", "Succeeded Jobs", "Failed Jobs", "Detail")
|
baseHeader ++ Seq("Running Jobs", "Succeeded Jobs", "Failed Jobs")
|
||||||
}
|
}
|
||||||
|
|
||||||
private[ui] class CompletedExecutionTable(
|
private[ui] class CompletedExecutionTable(
|
||||||
|
@ -215,7 +195,7 @@ private[ui] class CompletedExecutionTable(
|
||||||
showSucceededJobs = true,
|
showSucceededJobs = true,
|
||||||
showFailedJobs = false) {
|
showFailedJobs = false) {
|
||||||
|
|
||||||
override protected def header: Seq[String] = baseHeader ++ Seq("Jobs", "Detail")
|
override protected def header: Seq[String] = baseHeader ++ Seq("Jobs")
|
||||||
}
|
}
|
||||||
|
|
||||||
private[ui] class FailedExecutionTable(
|
private[ui] class FailedExecutionTable(
|
||||||
|
@ -234,5 +214,5 @@ private[ui] class FailedExecutionTable(
|
||||||
showFailedJobs = true) {
|
showFailedJobs = true) {
|
||||||
|
|
||||||
override protected def header: Seq[String] =
|
override protected def header: Seq[String] =
|
||||||
baseHeader ++ Seq("Succeeded Jobs", "Failed Jobs", "Detail")
|
baseHeader ++ Seq("Succeeded Jobs", "Failed Jobs")
|
||||||
}
|
}
|
||||||
|
|
|
@ -169,9 +169,9 @@ class UISeleniumSuite
|
||||||
List("4/4", "4/4", "4/4", "0/4 (1 failed)"))
|
List("4/4", "4/4", "4/4", "0/4 (1 failed)"))
|
||||||
|
|
||||||
// Check stacktrace
|
// Check stacktrace
|
||||||
val errorCells = findAll(cssSelector(""".stacktrace-details""")).map(_.text).toSeq
|
val errorCells = findAll(cssSelector(""".stacktrace-details""")).map(_.underlying).toSeq
|
||||||
errorCells should have size 1
|
errorCells should have size 1
|
||||||
errorCells(0) should include("java.lang.RuntimeException: Oops")
|
// Can't get the inner (invisible) text without running JS
|
||||||
|
|
||||||
// Check the job link in the batch page is right
|
// Check the job link in the batch page is right
|
||||||
go to (jobLinks(0))
|
go to (jobLinks(0))
|
||||||
|
|
Loading…
Reference in a new issue