From 349b70d3450418d20d2367b6ff2622fad42ea54e Mon Sep 17 00:00:00 2001 From: Elena Lepilkina Date: Thu, 21 Mar 2019 14:59:02 +0300 Subject: [PATCH] Fixes of perfromance server --- performance/build.gradle | 23 ++++---- .../src/main/kotlin/routes/route.kt | 32 ++++++----- tools/performance-server/ui/css/style.css | 20 +++++-- tools/performance-server/ui/index.ejs | 11 ++++ .../ui/src/main/kotlin/main.kt | 56 +++++++++++++------ 5 files changed, 96 insertions(+), 46 deletions(-) diff --git a/performance/build.gradle b/performance/build.gradle index e2d6ee5e27a..c6e2b9fa54e 100644 --- a/performance/build.gradle +++ b/performance/build.gradle @@ -82,17 +82,20 @@ private def uploadBenchmarkResultToBintray(String fileName) { } task registerBuild(type: BuildRegister) { - onlyBranch = project.findProperty('kotlin.register.branch') - // Get bundle size. - bundleSize = null - if (project.findProperty('kotlin.bundleBuild') != null) { - def dist = findProperty('org.jetbrains.kotlin.native.home') ?: 'dist' - dist = (new File(dist)).isAbsolute() ? dist : "${project.getProjectDir()}/$dist" - bundleSize = (new File(dist)).directorySize() - } - currentBenchmarksReportFile = "${buildDir.absolutePath}/${nativeJson}" - analyzer = MPPTools.findFile("${analyzerTool}${MPPTools.getNativeProgramExtension()}", + def analyzerBinary = MPPTools.findFile("${analyzerTool}${MPPTools.getNativeProgramExtension()}", "${rootBuildDirectory}/${analyzerToolDirectory}") + if (analyzerBinary != null) { + onlyBranch = project.findProperty('kotlin.register.branch') + // Get bundle size. + bundleSize = null + if (project.findProperty('kotlin.bundleBuild') != null) { + def dist = findProperty('org.jetbrains.kotlin.native.home') ?: 'dist' + dist = (new File(dist)).isAbsolute() ? dist : "${project.getProjectDir()}/$dist" + bundleSize = (new File(dist)).directorySize() + } + currentBenchmarksReportFile = "${buildDir.absolutePath}/${nativeJson}" + analyzer = analyzerBinary + } } def mergeReports(String fileName) { diff --git a/tools/performance-server/src/main/kotlin/routes/route.kt b/tools/performance-server/src/main/kotlin/routes/route.kt index aafb86f569a..74ac713d85d 100644 --- a/tools/performance-server/src/main/kotlin/routes/route.kt +++ b/tools/performance-server/src/main/kotlin/routes/route.kt @@ -67,16 +67,16 @@ object LocalCache { fun delete(target: String, builds: Iterable, bintrayUser: String, bintrayPassword: String): Boolean { // Delete from bintray. val buildsDescription = getBuildsInfoFromBintray(target).lines() - val initialBuildsNumber = buildsDescription.size - buildsDescription.filter { + + val newBuildsDescription = buildsDescription.filter { val buildNumber = it.substringBefore(',') buildNumber !in builds } - if (buildsDescription.size < initialBuildsNumber) { + if (newBuildsDescription.size < buildsDescription.size) { // Upload new version of file. val uploadUrl = "$uploadBintrayUrl/$bintrayPackage/latest/$target/$buildsFileName?publish=1&override=1" - sendUploadRequest(uploadUrl, buildsDescription.joinToString("\n"), bintrayUser, bintrayPassword) + sendUploadRequest(uploadUrl, newBuildsDescription.joinToString("\n"), bintrayUser, bintrayPassword) // Reload values. clean(target) @@ -189,7 +189,7 @@ fun getBuildsInfoFromBintray(target: String) = sendGetRequest("$downloadBintrayUrl/$target/$buildsFileName") // Parse and postprocess result of response with build description. -fun prepareBuildsResponse(builds: Collection, type: String, buildNumber: String? = null): List { +fun prepareBuildsResponse(builds: Collection, type: String, branch: String, buildNumber: String? = null): List { val buildsObjects = mutableListOf() builds.forEach { val tokens = it.split(",").map { it.trim() } @@ -197,7 +197,8 @@ fun prepareBuildsResponse(builds: Collection, type: String, buildNumber: error("Build description $it doesn't contain all necessary information. " + "File with data could be corrupted.") } - if (tokens[5] == type || type == "day" || tokens[0] == buildNumber) { + if ((tokens[5] == type || type == "day") && (branch == tokens[3] || branch == "all") + || tokens[0] == buildNumber) { buildsObjects.add(Build(tokens[0], tokens[1], tokens[2], tokens[3], tokens[4], tokens[5], tokens[6].toInt(), tokens[7], tokens[8], tokens[9], if (tokens[10] == "-") null else tokens[10])) @@ -233,7 +234,7 @@ fun router() { buildsDescription += "${buildInfo.buildNumber}, ${buildInfo.startTime}, ${buildInfo.finishTime}, " + "${buildInfo.branch}, $commitsDescription, ${register.buildType}, ${register.failuresNumber}, " + "${register.executionTime}, ${register.compileTime}, ${register.codeSize}, " + - "${register?.bundleSize ?: "-"}\n" + "${register.bundleSize ?: "-"}\n" // Upload new version of file. val uploadUrl = "$uploadBintrayUrl/$bintrayPackage/latest/${register.target}/${buildsFileName}?publish=1&override=1" @@ -247,22 +248,22 @@ fun router() { }) // Get list of builds. - router.get("/builds/:target/:type/:id", { request, response -> + router.get("/builds/:target/:type/:branch/:id", { request, response -> val builds = LocalCache[request.params.target, request.params.id] - response.json(prepareBuildsResponse(builds, request.params.type, request.params.id)) + response.json(prepareBuildsResponse(builds, request.params.type, request.params.branch, request.params.id)) }) - router.get("/builds/:target/:type", { request, response -> + router.get("/builds/:target/:type/:branch", { request, response -> val builds = LocalCache[request.params.target] - response.json(prepareBuildsResponse(builds, request.params.type)) + response.json(prepareBuildsResponse(builds, request.params.type, request.params.branch)) }) - router.get("/clean", { request, response -> + router.get("/clean", { _, response -> LocalCache.clean() response.sendStatus(200) }) - router.get("/fill", { request, response -> + router.get("/fill", { _, response -> LocalCache.fill() response.sendStatus(200) }) @@ -272,12 +273,13 @@ fun router() { val result = LocalCache.delete(request.params.target, buildsToDelete, request.query.user, request.query.key) if (result) { response.sendStatus(200) + } else { + response.sendStatus(404) } - response.sendStatus(404) }) // Main page. - router.get("/", { request, response -> + router.get("/", { _, response -> response.render("index") }) diff --git a/tools/performance-server/ui/css/style.css b/tools/performance-server/ui/css/style.css index bc153f024cd..6d604d90683 100644 --- a/tools/performance-server/ui/css/style.css +++ b/tools/performance-server/ui/css/style.css @@ -41,12 +41,12 @@ border-color: #d70206; } .ct-legend .ct-series-1:before { - background-color: #f05b4f; - border-color: #f05b4f; + background-color: gold; + border-color: gold; } .ct-legend .ct-series-2:before { - background-color: #f4c63d; - border-color: #f4c63d; + background-color: mediumorchid; + border-color: mediumorchid; } .ct-legend .ct-series-3:before { background-color: #d17905; @@ -55,4 +55,16 @@ .ct-legend .ct-series-4:before { background-color: #453d3f; border-color: #453d3f; +} + +.ct-series-b .ct-line, +.ct-series-b .ct-point { + /* Set the colour of this series line */ + stroke: gold; +} + +.ct-series-c .ct-line, +.ct-series-c .ct-point { + /* Set the colour of this series line */ + stroke: mediumorchid; } \ No newline at end of file diff --git a/tools/performance-server/ui/index.ejs b/tools/performance-server/ui/index.ejs index edbe3f56b4f..56eaf87d718 100644 --- a/tools/performance-server/ui/index.ejs +++ b/tools/performance-server/ui/index.ejs @@ -50,6 +50,17 @@ +
+
+
+ +
+ +
+
diff --git a/tools/performance-server/ui/src/main/kotlin/main.kt b/tools/performance-server/ui/src/main/kotlin/main.kt index 84408936c72..0419974577f 100644 --- a/tools/performance-server/ui/src/main/kotlin/main.kt +++ b/tools/performance-server/ui/src/main/kotlin/main.kt @@ -67,14 +67,19 @@ fun separateValues(values: String, valuesContainer: MutableMap, valuesList: Collection>): dynamic { +fun getChartData(labels: List, valuesList: Collection>, className: String? = null): dynamic { val chartData: dynamic = object{} chartData["labels"] = labels.toTypedArray() - chartData["series"] = valuesList.map { it.toTypedArray() }.toTypedArray() + chartData["series"] = valuesList.map { + val series: dynamic = object{} + series["data"] = it.toTypedArray() + className?.let { series["className"] = className } + series + }.toTypedArray() return chartData } -fun getChartOptions(samples: Array, yTitle: String): dynamic { +fun getChartOptions(samples: Array, yTitle: String, classNames: Array? = null): dynamic { val chartOptions: dynamic = object{} chartOptions["fullWidth"] = true val paddingObject: dynamic = object{} @@ -88,6 +93,7 @@ fun getChartOptions(samples: Array, yTitle: String): dynamic { chartOptions["axisY"] = axisYObject val legendObject: dynamic = object{} legendObject["legendNames"] = samples + classNames?.let { legendObject["classNames"] = classNames } val titleObject: dynamic = object{} val axisYTitle: dynamic = object{} axisYTitle["axisTitle"] = yTitle @@ -103,6 +109,10 @@ fun getChartOptions(samples: Array, yTitle: String): dynamic { return chartOptions } +fun redirect(url: String) { + window.location.href = url +} + fun customizeChart(chart: dynamic, chartContainer: String, jquerySelector: dynamic, builds: List, parameters: Map) { chart.on("draw", { data -> @@ -155,7 +165,7 @@ fun customizeChart(chart: dynamic, chartContainer: String, jquerySelector: dynam element._node.setAttribute("title", information) element._node.setAttribute("data-chart-tooltip", chartContainer) element._node.addEventListener("click", { - window.location.replace(linkToDetailedInfo) + redirect(linkToDetailedInfo) }) } }) @@ -175,7 +185,7 @@ fun main(args: Array) { // Get parameters from request. val url = window.location.href val parametersPart = url.substringAfter("?").split('&') - val parameters = mutableMapOf("target" to "Linux", "type" to "dev", "build" to "") + val parameters = mutableMapOf("target" to "Linux", "type" to "dev", "build" to "", "branch" to "master") parametersPart.forEach { val parsedParameter = it.split("=", limit = 2) if (parsedParameter.size == 2) { @@ -189,6 +199,7 @@ fun main(args: Array) { append("$serverUrl") append("/${parameters["target"]}") append("/${parameters["type"]}") + append("/${parameters["branch"]}") append("/${parameters["build"]}") } val response = sendGetRequest(buildsUrl) @@ -205,23 +216,32 @@ fun main(args: Array) { // Change inputs values connected with parameters and add events listeners. document.querySelector("#inputGroupTarget [value=\"${parameters["target"]}\"]")?.setAttribute("selected", "true") document.querySelector("#inputGroupBuildType [value=\"${parameters["type"]}\"]")?.setAttribute("selected", "true") + document.querySelector("#inputGroupBranch [value=\"${parameters["branch"]}\"]")?.setAttribute("selected", "true") (document.getElementById("highligted_build") as HTMLInputElement).value = parameters["build"]!! // Add onChange events for fields. js("$('#inputGroupTarget')").change({ val newValue = js("$(this).val()") if (newValue != parameters["target"]) { - val newLink = "http://${window.location.host}/?target=$newValue&type=${parameters["type"]}" + + val newLink = "http://${window.location.host}/?target=$newValue&type=${parameters["type"]}&branch=${parameters["branch"]}" + "${if (parameters["build"]!!.isEmpty()) "" else "&build=${parameters["build"]}"}" - window.location.replace(newLink) + window.location.href = newLink } }) js("$('#inputGroupBuildType')").change({ val newValue = js("$(this).val()") if (newValue != parameters["type"]) { - val newLink = "http://${window.location.host}/?target=${parameters["target"]}&type=$newValue" + + val newLink = "http://${window.location.host}/?target=${parameters["target"]}&type=$newValue&branch=${parameters["branch"]}" + "${if (parameters["build"]!!.isEmpty()) "" else "&build=${parameters["build"]}"}" - window.location.replace(newLink) + window.location.href = newLink + } + }) + js("$('#inputGroupBranch')").change({ + val newValue = js("$(this).val()") + if (newValue != parameters["branch"]) { + val newLink = "http://${window.location.host}/?target=${parameters["target"]}&type=${parameters["type"]}&branch=$newValue" + + "${if (parameters["build"]!!.isEmpty()) "" else "&build=${parameters["build"]}"}" + window.location.href = newLink } }) @@ -231,7 +251,7 @@ fun main(args: Array) { if (suggestion.value != parameters["build"]) { val newLink = "http://${window.location.host}/?target=${parameters["target"]}&type=${parameters["type"]}" + "${if (suggestion.value.isEmpty()) "" else "&build=${suggestion.value}"}" - window.location.replace(newLink) + window.location.href = newLink } } js("$( \"#highligted_build\" )").autocomplete(autocompleteParameters) @@ -240,7 +260,7 @@ fun main(args: Array) { if (newValue.isEmpty() || newValue in builds.map {it.buildNumber}) { val newLink = "http://${window.location.host}/?target=${parameters["target"]}&type=${parameters["type"]}" + "${if (newValue.isEmpty()) "" else "&build=$newValue"}" - window.location.replace(newLink) + window.location.href = newLink } }) @@ -260,20 +280,22 @@ fun main(args: Array) { labels.add(it.buildNumber) } separateValues(it.executionTime, executionTime) { value -> value.toDouble() } - separateValues(it.compileTime, compileTime) { value -> value.toDouble() } + separateValues(it.compileTime, compileTime) { value -> value.toDouble() / 1000 } separateValues(it.codeSize, codeSize) { value -> value.toDouble() / 1024.0 } bundleSize.add(it.bundleSize?.toInt()?. let { it / 1024 / 1024 }) } + val sizeClassName = "ct-series-c" + // Draw charts. val execChart = Chartist.Line("#exec_chart", getChartData(labels, executionTime.values), getChartOptions(executionTime.keys.toTypedArray(), "Time, microseconds")) val compileChart = Chartist.Line("#compile_chart", getChartData(labels, compileTime.values), - getChartOptions(compileTime.keys.toTypedArray(), "Time, microseconds")) - val codeSizeChart = Chartist.Line("#codesize_chart", getChartData(labels, codeSize.values), - getChartOptions(codeSize.keys.toTypedArray(), "Size, KB")) - val bundleSizeChart = Chartist.Line("#bundlesize_chart", getChartData(labels, listOf(bundleSize)), - getChartOptions(arrayOf("Bundle size"), "Size, MB")) + getChartOptions(compileTime.keys.toTypedArray(), "Time, milliseconds")) + val codeSizeChart = Chartist.Line("#codesize_chart", getChartData(labels, codeSize.values, sizeClassName), + getChartOptions(codeSize.keys.toTypedArray(), "Size, KB", arrayOf("ct-series-2"))) + val bundleSizeChart = Chartist.Line("#bundlesize_chart", getChartData(labels, listOf(bundleSize), sizeClassName), + getChartOptions(arrayOf("Bundle size"), "Size, MB", arrayOf("ct-series-2"))) // Tooltips and higlights. customizeChart(execChart, "exec_chart", js("$(\"#exec_chart\")"), builds, parameters)