Add option to use regexes for filtering and add property for passing compiler args when running benchmarks. (#2894)

This commit is contained in:
Mark Punzalan
2019-04-24 00:18:22 -07:00
committed by LepilkinaElena
parent a764723e4f
commit 6d544cd667
8 changed files with 64 additions and 33 deletions
+13 -2
View File
@@ -110,15 +110,26 @@ To update the blackbox compiler tests set TeamCity build number in `gradle.prope
../gradlew :cinterop:konanRun ../gradlew :cinterop:konanRun
**konanRun** task has parameter `filter` which allows to run only some subset of benchmarks : **konanRun** task has parameter `filter` which allows to run only some subset of benchmarks:
../gradlew :cinterop:konanRun --filter=struct,macros ../gradlew :cinterop:konanRun --filter=struct,macros
Or you can use `filterRegex` if you want to specify the filter as regexes:
../gradlew :ring:konanRun --filterRegex=String.*,Loop.*
There are also tasks for running benchmarks on JVM (pay attention, some benchmarks e.g. cinterop benchmarks can't be run on JVM) There are also tasks for running benchmarks on JVM (pay attention, some benchmarks e.g. cinterop benchmarks can't be run on JVM)
../gradlew jvmRun ../gradlew jvmRun
Files with results of benchmarks run are saved in `performance/build`. **nativeReport.json** - for konanRun and **jvmReport.json** for jvmRun. Files with results of benchmarks run are saved in `performance/build/nativeReport.json` for konanRun and `jvmReport.json` for jvmRun.
You can change the output filename by setting the `nativeJson` property for konanRun and `jvmJson` for jvmRun:
../gradlew :ring:konanRun --filter=String.*,Loop.* -PnativeJson=stringsAndLoops.json
You can use the `compilerArgs` property to pass flags to the compiler used to compile the benchmarks:
../gradlew konanRun -PcompilerArgs="--time -g"
To compare different results run benchmarksAnalyzer tool: To compare different results run benchmarksAnalyzer tool:
@@ -13,27 +13,31 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
import javax.inject.Inject import javax.inject.Inject
import java.io.File import java.io.File
open class RunJvmTask: JavaExec() { open class RunJvmTask : JavaExec() {
var outputFileName: String? = null var outputFileName: String? = null
@Input @Input
@Option(option = "filter", description = "filter") @Option(option = "filter", description = "Benchmarks to run (comma-separated)")
var filter: String = "" var filter: String = ""
@Input
@Option(option = "filterRegex", description = "Benchmarks to run, described by regular expressions (comma-separated)")
var filterRegex: String = ""
override fun configure(configureClosure: Closure<Any>): Task { override fun configure(configureClosure: Closure<Any>): Task {
return super.configure(configureClosure) return super.configure(configureClosure)
} }
private fun executeTask(output: java.io.OutputStream? = null) { private fun executeTask(output: java.io.OutputStream? = null) {
val filterArgs = filter.split("\\s*,\\s*".toRegex()) val filterArgs = filter.splitCommaSeparatedOption("-f")
.map{ if (it.isNotEmpty()) listOf("-f", it) else listOf(null) }.flatten().filterNotNull() val filterRegexArgs = filterRegex.splitCommaSeparatedOption("-fr")
args(filterArgs) args(filterArgs)
args(filterRegexArgs)
exec() exec()
} }
@TaskAction @TaskAction
fun run() { fun run() {
if (outputFileName != null) if (outputFileName != null)
File(outputFileName).outputStream().use { output -> executeTask(output)} File(outputFileName).outputStream().use { output -> executeTask(output) }
else else
executeTask() executeTask()
} }
@@ -15,14 +15,17 @@ import java.io.File
open class RunKotlinNativeTask @Inject constructor( open class RunKotlinNativeTask @Inject constructor(
private val curTarget: KotlinTarget private val curTarget: KotlinTarget
): DefaultTask() { ) : DefaultTask() {
var buildType = "RELEASE" var buildType = "RELEASE"
var workingDir: Any = project.projectDir var workingDir: Any = project.projectDir
var outputFileName: String? = null var outputFileName: String? = null
@Input @Input
@Option(option = "filter", description = "filter") @Option(option = "filter", description = "Benchmarks to run (comma-separated)")
var filter: String = "" var filter: String = ""
@Input
@Option(option = "filterRegex", description = "Benchmarks to run, described by regular expressions (comma-separated)")
var filterRegex: String = ""
private var curArgs: List<String> = emptyList() private var curArgs: List<String> = emptyList()
private val curEnvironment: MutableMap<String, Any> = mutableMapOf() private val curEnvironment: MutableMap<String, Any> = mutableMapOf()
@@ -46,11 +49,11 @@ open class RunKotlinNativeTask @Inject constructor(
} }
private fun executeTask(output: java.io.OutputStream? = null) { private fun executeTask(output: java.io.OutputStream? = null) {
val filterArgs = filter.split("\\s*,\\s*".toRegex()) val filterArgs = filter.splitCommaSeparatedOption("-f")
.map{ if (it.isNotEmpty()) listOf("-f", it) else listOf(null) }.flatten().filterNotNull() val filterRegexArgs = filterRegex.splitCommaSeparatedOption("-fr")
project.exec { project.exec {
it.executable = curTarget.compilations.main.getBinary("EXECUTABLE", buildType).toString() it.executable = curTarget.compilations.main.getBinary("EXECUTABLE", buildType).toString()
it.args = curArgs + filterArgs it.args = curArgs + filterArgs + filterRegexArgs
it.environment = curEnvironment it.environment = curEnvironment
it.workingDir(workingDir) it.workingDir(workingDir)
if (output != null) if (output != null)
@@ -61,7 +64,7 @@ open class RunKotlinNativeTask @Inject constructor(
@TaskAction @TaskAction
fun run() { fun run() {
if (outputFileName != null) if (outputFileName != null)
File(outputFileName).outputStream().use { output -> executeTask(output)} File(outputFileName).outputStream().use { output -> executeTask(output) }
else else
executeTask() executeTask()
} }
@@ -29,6 +29,11 @@ fun Array<String>.runCommand(workingDir: File = File("."),
} }
} }
fun String.splitCommaSeparatedOption(optionName: String) =
split("\\s*,\\s*".toRegex()).map {
if (it.isNotEmpty()) listOf(optionName, it) else listOf(null)
}.flatten().filterNotNull()
data class Commit(val revision: String, val developer: String, val webUrlWithDescription: String) data class Commit(val revision: String, val developer: String, val webUrlWithDescription: String)
val teamCityUrl = "http://buildserver.labs.intellij.net" val teamCityUrl = "http://buildserver.labs.intellij.net"
+3 -2
View File
@@ -21,7 +21,7 @@ import org.jetbrains.structsBenchmarks.*
import org.jetbrains.typesBenchmarks.* import org.jetbrains.typesBenchmarks.*
import org.jetbrains.kliopt.* import org.jetbrains.kliopt.*
class CinteropLauncher(numWarmIterations: Int, numberOfAttempts: Int, prefix: String): Launcher(numWarmIterations, numberOfAttempts, prefix) { class CinteropLauncher(numWarmIterations: Int, numberOfAttempts: Int, prefix: String) : Launcher(numWarmIterations, numberOfAttempts, prefix) {
val stringBenchmark = StringBenchmark() val stringBenchmark = StringBenchmark()
val intMatrixBenchmark = IntMatrixBenchmark() val intMatrixBenchmark = IntMatrixBenchmark()
val intBenchmark = IntBenchmark() val intBenchmark = IntBenchmark()
@@ -43,6 +43,7 @@ class CinteropLauncher(numWarmIterations: Int, numberOfAttempts: Int, prefix: St
fun main(args: Array<String>) { fun main(args: Array<String>) {
BenchmarksRunner.runBenchmarks(args, { parser: ArgParser -> BenchmarksRunner.runBenchmarks(args, { parser: ArgParser ->
CinteropLauncher(parser.get<Int>("warmup")!!, parser.get<Int>("repeat")!!, parser.get<String>("prefix")!!).launch(parser.getAll<String>("filter")) CinteropLauncher(parser.get<Int>("warmup")!!, parser.get<Int>("repeat")!!, parser.get<String>("prefix")!!)
.launch(parser.getAll<String>("filter"), parser.getAll<String>("filterRegex"))
}) })
} }
+3 -3
View File
@@ -13,7 +13,6 @@ repositories {
} }
private def determinePreset() { private def determinePreset() {
def preset = MPPTools.defaultHostPreset(project) def preset = MPPTools.defaultHostPreset(project)
println("$project has been configured for ${preset.name} platform.") println("$project has been configured for ${preset.name} platform.")
@@ -53,14 +52,15 @@ kotlin {
compilations.all { compilations.all {
tasks[compileKotlinTaskName].kotlinOptions { tasks[compileKotlinTaskName].kotlinOptions {
jvmTarget = '1.8' jvmTarget = '1.8'
suppressWarnings = true
freeCompilerArgs = (project.hasProperty('compilerArgs') ? compilerArgs.split() : [])
} }
tasks[compileKotlinTaskName].kotlinOptions.suppressWarnings = true
} }
} }
fromPreset(hostPreset, 'native') { fromPreset(hostPreset, 'native') {
compilations.main.outputKinds('EXECUTABLE') compilations.main.outputKinds('EXECUTABLE')
compilations.main.extraOpts '-opt' compilations.main.extraOpts = (project.hasProperty('compilerArgs') ? compilerArgs.split() : []) + '-opt'
compilations.main.buildTypes = [RELEASE] compilations.main.buildTypes = [RELEASE]
} }
} }
+3 -2
View File
@@ -20,7 +20,7 @@ import octoTest
import org.jetbrains.benchmarksLauncher.* import org.jetbrains.benchmarksLauncher.*
import org.jetbrains.kliopt.* import org.jetbrains.kliopt.*
class RingLauncher(numWarmIterations: Int, numberOfAttempts: Int, prefix: String): Launcher(numWarmIterations, numberOfAttempts, prefix) { class RingLauncher(numWarmIterations: Int, numberOfAttempts: Int, prefix: String) : Launcher(numWarmIterations, numberOfAttempts, prefix) {
val abstractMethodBenchmark = AbstractMethodBenchmark() val abstractMethodBenchmark = AbstractMethodBenchmark()
val classArrayBenchmark = ClassArrayBenchmark() val classArrayBenchmark = ClassArrayBenchmark()
val classBaselineBenchmark = ClassBaselineBenchmark() val classBaselineBenchmark = ClassBaselineBenchmark()
@@ -232,6 +232,7 @@ class RingLauncher(numWarmIterations: Int, numberOfAttempts: Int, prefix: String
fun main(args: Array<String>) { fun main(args: Array<String>) {
BenchmarksRunner.runBenchmarks(args, { parser: ArgParser -> BenchmarksRunner.runBenchmarks(args, { parser: ArgParser ->
RingLauncher(parser.get<Int>("warmup")!!, parser.get<Int>("repeat")!!, parser.get<String>("prefix")!!).launch(parser.getAll<String>("filter")) RingLauncher(parser.get<Int>("warmup")!!, parser.get<Int>("repeat")!!, parser.get<String>("prefix")!!)
.launch(parser.getAll<String>("filter"), parser.getAll<String>("filterRegex"))
}) })
} }
@@ -25,13 +25,18 @@ abstract class Launcher(val numWarmIterations: Int, val numberOfAttempts: Int, v
abstract val benchmarks: BenchmarksCollection abstract val benchmarks: BenchmarksCollection
protected val benchmarkResults = mutableListOf<BenchmarkResult>() fun launch(filters: Collection<String>? = null,
filterRegexes: Collection<String>? = null): List<BenchmarkResult> {
fun launch(benchmarksToRun: Collection<String>? = null): List<BenchmarkResult> { val regexes = filterRegexes?.map { it.toRegex() } ?: listOf()
val runningBenchmarks = benchmarksToRun ?: benchmarks.keys val filterSet = filters?.toHashSet() ?: hashSetOf()
runningBenchmarks.forEach { // Filter benchmarks using given filters, or run all benchmarks if none were given.
val benchmark = benchmarks[it] val runningBenchmarks = if (filterSet.isNotEmpty() || regexes.isNotEmpty()) {
benchmark ?: error("Benchmark $it wasn't found!") benchmarks.filterKeys { benchmark -> benchmark in filterSet || regexes.any { it.matches(benchmark) } }
} else benchmarks
if (runningBenchmarks.isEmpty())
error("No matching benchmarks found")
val benchmarkResults = mutableListOf<BenchmarkResult>()
for ((name, benchmark) in runningBenchmarks) {
var i = numWarmIterations var i = numWarmIterations
while (i-- > 0) benchmark() while (i-- > 0) benchmark()
cleanup() cleanup()
@@ -60,7 +65,7 @@ abstract class Launcher(val numWarmIterations: Int, val numberOfAttempts: Int, v
val scaledTime = time * 1.0 / autoEvaluatedNumberOfMeasureIteration val scaledTime = time * 1.0 / autoEvaluatedNumberOfMeasureIteration
samples[k] = scaledTime samples[k] = scaledTime
// Save benchmark object // Save benchmark object
benchmarkResults.add(BenchmarkResult("$prefix$it", BenchmarkResult.Status.PASSED, benchmarkResults.add(BenchmarkResult("$prefix$name", BenchmarkResult.Status.PASSED,
scaledTime / 1000, BenchmarkResult.Metric.EXECUTION_TIME, scaledTime / 1000, scaledTime / 1000, BenchmarkResult.Metric.EXECUTION_TIME, scaledTime / 1000,
k + 1, numWarmIterations)) k + 1, numWarmIterations))
} }
@@ -73,10 +78,11 @@ object BenchmarksRunner {
fun parse(args: Array<String>): ArgParser { fun parse(args: Array<String>): ArgParser {
val options = listOf( val options = listOf(
OptionDescriptor(ArgType.Int(), "warmup", "w", "Number of warm up iterations", "20"), OptionDescriptor(ArgType.Int(), "warmup", "w", "Number of warm up iterations", "20"),
OptionDescriptor(ArgType.Int(), "repeat", "r", "Number of each becnhmark run", "60"), OptionDescriptor(ArgType.Int(), "repeat", "r", "Number of each benchmark run", "60"),
OptionDescriptor(ArgType.String(), "prefix", "p", "Prefix added to benchmark name", ""), OptionDescriptor(ArgType.String(), "prefix", "p", "Prefix added to benchmark name", ""),
OptionDescriptor(ArgType.String(), "output", "o", "Output file"), OptionDescriptor(ArgType.String(), "output", "o", "Output file"),
OptionDescriptor(ArgType.String(), "filter", "f", "Benchmark to run", isMultiple = true) OptionDescriptor(ArgType.String(), "filter", "f", "Benchmark to run", isMultiple = true),
OptionDescriptor(ArgType.String(), "filterRegex", "fr", "Benchmark to run, described by a regular expression", isMultiple = true)
) )
// Parse args. // Parse args.