diff --git a/build-tools/src/main/kotlin/org/jetbrains/kotlin/BuildRegister.kt b/build-tools/src/main/kotlin/org/jetbrains/kotlin/BuildRegister.kt index bddc5dd7ab5..b6bab51e040 100644 --- a/build-tools/src/main/kotlin/org/jetbrains/kotlin/BuildRegister.kt +++ b/build-tools/src/main/kotlin/org/jetbrains/kotlin/BuildRegister.kt @@ -5,30 +5,21 @@ package org.jetbrains.kotlin -import groovy.lang.Closure -import org.gradle.api.Action import org.gradle.api.DefaultTask -import org.gradle.api.Project -import org.gradle.api.Task import org.gradle.api.tasks.Input import org.gradle.api.tasks.TaskAction -import com.ullink.slack.simpleslackapi.impl.SlackSessionFactory - import org.jetbrains.report.json.* import java.io.FileInputStream -import java.io.IOException -import java.io.File import java.io.OutputStreamWriter import java.io.BufferedReader import java.io.InputStreamReader -import java.util.concurrent.TimeUnit import java.net.HttpURLConnection import java.net.URL -import java.util.Base64 import java.util.Properties +typealias performanceAdditionalResult = Triple /** * Task to produce regressions report and send it to slack. Requires a report with current benchmarks result * and path to analyzer tool @@ -49,7 +40,7 @@ open class BuildRegister : DefaultTask() { var bundleSize: Int? = null val buildInfoTokens: Int = 4 - val frameworkInfoTokens: Int = 3 + val additionalInfoTokens: Int = 3 val compileTimeSamplesNumber: Int = 2 val buildNumberTokens: Int = 3 val performanceServer = "https://kotlin-native-perf-summary.labs.jb.gg" @@ -80,6 +71,30 @@ open class BuildRegister : DefaultTask() { } } + fun getAdditionalInfo(analyzer: String, reportFile: String, alwaysExists: Boolean, benchmarkName: String, + showedName: String = benchmarkName) : + performanceAdditionalResult? { + val output = arrayOf(analyzer, "summary", "--compile", "samples", + "--compile-samples", benchmarkName, "--codesize-samples", benchmarkName, + "--codesize-normalize", "artifactory:builds/goldenResults.csv", reportFile) + .runCommand() + + + val buildInfoParts = output.split(',') + if (buildInfoParts.size != additionalInfoTokens) { + val message = "Problems with getting summary information using $analyzer and $reportFile. $output" + if (!alwaysExists) { + println(message) + return null + } + error(message) + } + val (failures, compileTime, codeSize) = buildInfoParts.map { it.trim() } + val codeSizeInfo = "$showedName-$codeSize" + val compileTimeInfo = "$showedName-$compileTime" + return performanceAdditionalResult(failures, compileTimeInfo, codeSizeInfo) + } + @TaskAction fun run() { // Get TeamCity properties. @@ -114,6 +129,7 @@ open class BuildRegister : DefaultTask() { } val (failures, executionTime, compileTime, codeSize) = buildInfoParts.map { it.trim() } + var failuresNumber = failures.toInt() // Add legends. val geometricMean = "Geometric Mean-" val executionTimeInfo = "$geometricMean$executionTime" @@ -127,19 +143,35 @@ open class BuildRegister : DefaultTask() { // Collect framework run details. if (target == "MacOSX") { - - val frameworkOutput = arrayOf("$analyzer", "summary", "--compile", "samples", - "--compile-samples", "FrameworkBenchmarksAnalyzer", "--codesize-samples", "FrameworkBenchmarksAnalyzer", - "--codesize-normalize", "artifactory:builds/goldenResults.csv", "$currentBenchmarksReportFile") - .runCommand() - - val buildInfoPartsFramework = frameworkOutput.split(',') - if (buildInfoPartsFramework.size != frameworkInfoTokens) { - error("Problems with getting summary information using $analyzer and $currentBenchmarksReportFile. $frameworkOutput") + val frameworkResults = getAdditionalInfo(analyzer, currentBenchmarksReportFile, true, + "FrameworkBenchmarksAnalyzer") + frameworkResults?.let { + val (_, frameworkCompileTime, frameworkCodeSize) = it + codeSizeInfo += ";$frameworkCodeSize" + compileTimeInfo += ";$frameworkCompileTime" + } + + val spaceResults = getAdditionalInfo(analyzer, + "artifactory:$buildNumber:$target:spaceFrameworkReport.json", false, + "circlet_iosX64", "SpaceFramework_iosX64") + spaceResults?.let { + val (failures, frameworkCompileTime, frameworkCodeSize) = it + failuresNumber += failures.toInt() + codeSizeInfo += ";$frameworkCodeSize" + compileTimeInfo += ";$frameworkCompileTime" + } + } + + if (target == "Linux") { + val coroutinesResults = getAdditionalInfo(analyzer, + "artifactory:$buildNumber:$target:externalReport.json", false, + "kotlinx.coroutines") + coroutinesResults?.let { + val (failures, libraryCompileTime, libraryCodeSize) = it + failuresNumber += failures.toInt() + codeSizeInfo += ";$libraryCodeSize" + compileTimeInfo += ";$libraryCompileTime" } - val (_, frameworkCompileTime, frameworkCodeSize) = buildInfoPartsFramework.map { it.trim() } - codeSizeInfo += ";FrameworkBenchmarksAnalyzer-$frameworkCodeSize" - compileTimeInfo += ";FrameworkBenchmarksAnalyzer-$frameworkCompileTime" } val buildNumberParts = buildNumber.split("-") @@ -156,7 +188,7 @@ open class BuildRegister : DefaultTask() { append("\"artifactoryApiKey\":\"$apiKey\",") append("\"target\": \"$target\",") append("\"buildType\": \"$buildType\",") - append("\"failuresNumber\": $failures,") + append("\"failuresNumber\": $failuresNumber,") append("\"executionTime\": \"$executionTimeInfo\",") append("\"compileTime\": \"$compileTimeInfo\",") append("\"codeSize\": \"$codeSizeInfo\",") diff --git a/build-tools/src/main/kotlin/org/jetbrains/kotlin/Utils.kt b/build-tools/src/main/kotlin/org/jetbrains/kotlin/Utils.kt index d697010d027..e183f89b708 100644 --- a/build-tools/src/main/kotlin/org/jetbrains/kotlin/Utils.kt +++ b/build-tools/src/main/kotlin/org/jetbrains/kotlin/Utils.kt @@ -139,7 +139,7 @@ fun Array.runCommand(workingDir: File = File("."), .start().apply { waitFor(timeoutAmount, timeoutUnit) }.inputStream.bufferedReader().readText() - } catch (e: IOException) { + } catch (e: Exception) { error("Couldn't run command $this") } } diff --git a/tools/benchmarksAnalyzer/src/main/kotlin-native/org/jetbrains/analyzer/Utils.kt b/tools/benchmarksAnalyzer/src/main/kotlin-native/org/jetbrains/analyzer/Utils.kt index 7a80fafd151..f5e4d72c0ad 100644 --- a/tools/benchmarksAnalyzer/src/main/kotlin-native/org/jetbrains/analyzer/Utils.kt +++ b/tools/benchmarksAnalyzer/src/main/kotlin-native/org/jetbrains/analyzer/Utils.kt @@ -78,9 +78,16 @@ class CUrl(url: String, user: String? = null, password: String? = null, followLo val body = StringBuilder() fun fetch() { - val res = curl_easy_perform(curl) - if (res != CURLE_OK) - println("curl_easy_perform() failed: ${curl_easy_strerror(res)?.toKString()}") + memScoped { + val res = curl_easy_perform(curl) + if (res != CURLE_OK) + error("curl_easy_perform() failed: ${curl_easy_strerror(res)?.toKString()}") + val http_code = alloc() + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, http_code.ptr) + if (http_code.value >= 400L) { + error("Error http code ${http_code.value}") + } + } } fun close() { diff --git a/tools/performance-server/ui/css/style.css b/tools/performance-server/ui/css/style.css index 20e250c4ee9..952a6724da2 100644 --- a/tools/performance-server/ui/css/style.css +++ b/tools/performance-server/ui/css/style.css @@ -48,14 +48,26 @@ background-color: limegreen; border-color: limegreen; } + .ct-legend .ct-series-3:before { + background-color: lightsalmon; + border-color: lightsalmon; +} + +.ct-legend .ct-series-4:before { background-color: mediumorchid; border-color: mediumorchid; } -.ct-legend .ct-series-4:before { +.ct-legend .ct-series-5:before { background-color: navy; border-color: navy; } + +.ct-legend .ct-series-6:before { + background-color: darkcyan; + border-color: darkcyan; +} + .ct-legend .ct-series-5:before { background-color: #453d3f; border-color: #453d3f; @@ -76,12 +88,24 @@ .ct-series-d .ct-line, .ct-series-d .ct-point { /* Set the colour of this series line */ - stroke: mediumorchid; + stroke: lightsalmon; } .ct-series-e .ct-line, .ct-series-e .ct-point { + /* Set the colour of this series line */ + stroke: mediumorchid; +} + +.ct-series-f .ct-line, +.ct-series-f .ct-point { /* Set the colour of this series line */ stroke: navy; } + +.ct-series-g .ct-line, +.ct-series-g .ct-point { + /* Set the colour of this series line */ + stroke: darkcyan; +} .tooltip { pointer-events: none; } \ No newline at end of file diff --git a/tools/performance-server/ui/src/main/kotlin/main.kt b/tools/performance-server/ui/src/main/kotlin/main.kt index dda2612dc6c..9b9364cdc09 100644 --- a/tools/performance-server/ui/src/main/kotlin/main.kt +++ b/tools/performance-server/ui/src/main/kotlin/main.kt @@ -347,7 +347,7 @@ fun main(args: Array) { bundleSize.add(it.bundleSize?.toInt()?. let { it / 1024 / 1024 }) } - val sizeClassNames = arrayOf("ct-series-d", "ct-series-e") + val sizeClassNames = arrayOf("ct-series-e", "ct-series-f", "ct-series-g") // Draw charts. val execChart = Chartist.Line("#exec_chart", getChartData(labels, executionTime.values, stageToShow, buildsNumberToShow), @@ -355,9 +355,9 @@ fun main(args: Array) { val compileChart = Chartist.Line("#compile_chart", getChartData(labels, compileTime.values, stageToShow, buildsNumberToShow), getChartOptions(compileTime.keys.toTypedArray(), "Time, milliseconds")) val codeSizeChart = Chartist.Line("#codesize_chart", getChartData(labels, codeSize.values, stageToShow, buildsNumberToShow, sizeClassNames), - getChartOptions(codeSize.keys.toTypedArray(), "Normalized size", arrayOf("ct-series-3", "ct-series-4"))) + getChartOptions(codeSize.keys.toTypedArray(), "Normalized size", arrayOf("ct-series-4", "ct-series-5", "ct-series-6"))) val bundleSizeChart = Chartist.Line("#bundlesize_chart", getChartData(labels, listOf(bundleSize), stageToShow, buildsNumberToShow, sizeClassNames), - getChartOptions(arrayOf("Bundle size"), "Size, MB", arrayOf("ct-series-3"))) + getChartOptions(arrayOf("Bundle size"), "Size, MB", arrayOf("ct-series-4"))) // Tooltips and higlights. customizeChart(execChart, "exec_chart", js("$(\"#exec_chart\")"), builds, parameters)