Skip to content

Commit af47e3a

Browse files
Abduqodiri Qurbonzodaqurbonzoda
authored andcommitted
[K/JVM] Provide a config option to not override fork value defined in @fork
Additionally rename "forks" configuration option to "jvmForks".
1 parent db65f2e commit af47e3a

File tree

4 files changed

+42
-15
lines changed

4 files changed

+42
-15
lines changed

README.md

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -148,14 +148,20 @@ Available configuration options:
148148
* `mode`
149149
- "thrpt" (default) – measures number of benchmark function invocations per time
150150
- "avgt" – measures time per benchmark function invocation
151-
* `nativeFork`
152-
- "perBenchmark" (default) – executes all iterations of a benchmark in the same process (one binary execution)
153-
- "perIteration" – executes each iteration of a benchmark in a separate process, measures in cold Kotlin/Native runtime environment
154-
* `nativeGCAfterIteration` – when set to `true`, additionally collects garbage after each measuring iteration (default is `false`).
155151
* `include("…")` – regular expression to include benchmarks with fully qualified names matching it, as a substring
156152
* `exclude("…")` – regular expression to exclude benchmarks with fully qualified names matching it, as a substring
157153
* `param("name", "value1", "value2")` – specify a parameter for a public mutable property `name` annotated with `@Param`
158154
* `reportFormat` – format of report, can be `json`(default), `csv`, `scsv` or `text`
155+
* There are also some advanced platform-specific settings that can be configured using `advanced("…", …)` function,
156+
where the first argument is the name of the configuration parameter, and the second is its value. Valid options:
157+
* (Kotlin/Native) `nativeFork`
158+
- "perBenchmark" (default) – executes all iterations of a benchmark in the same process (one binary execution)
159+
- "perIteration" – executes each iteration of a benchmark in a separate process, measures in cold Kotlin/Native runtime environment
160+
* (Kotlin/Native) `nativeGCAfterIteration` – when set to `true`, additionally collects garbage after each measuring iteration (default is `false`).
161+
* (Kotlin/JVM) `jvmForks` – number of times harness should fork (default is `1`)
162+
- a non-negative integer value – the amount to use for all benchmarks included in this configuration, zero means "no fork"
163+
- "definedByJmh" – let the underlying JMH determine, which uses the amount specified in [`@Fork` annotation](https://javadoc.io/static/org.openjdk.jmh/jmh-core/1.21/org/openjdk/jmh/annotations/Fork.html) defined for the benchmark function or its enclosing class,
164+
or [Defaults.MEASUREMENT_FORKS (`5`)](https://javadoc.io/static/org.openjdk.jmh/jmh-core/1.21/org/openjdk/jmh/runner/Defaults.html#MEASUREMENT_FORKS) if it is not specified by `@Fork`.
159165

160166
Time units can be NANOSECONDS, MICROSECONDS, MILLISECONDS, SECONDS, MINUTES, or their short variants such as "ms" or "ns".
161167

examples/kotlin-multiplatform/build.gradle

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,11 @@ kotlin {
5858
// Configure benchmark
5959
benchmark {
6060
configurations {
61-
main { // --> jvmBenchmark/jsBenchmark + benchmark
61+
main { // --> jvmBenchmark, jsBenchmark, <native target>Benchmark, benchmark
6262
iterations = 5 // number of iterations
6363
iterationTime = 300
6464
iterationTimeUnit = "ms"
65-
advanced("forks", 3)
65+
advanced("jvmForks", 3)
6666
}
6767

6868
params {
@@ -74,14 +74,12 @@ benchmark {
7474
param("unused", 6, 9)
7575
}
7676

77-
fast { // --> jvmFastBenchmark
77+
fast { // --> jvmFastBenchmark, jsFastBenchmark, <native target>FastBenchmark, fastBenchmark
7878
include("Common")
7979
exclude("long")
8080
iterations = 5
8181
iterationTime = 300 // time in ms per iteration
8282
iterationTimeUnit = "ms" // time in ms per iteration
83-
advanced("forks", 1)
84-
advanced("nativeFork", "perIteration")
8583
advanced("nativeGCAfterIteration", "true")
8684
}
8785

@@ -93,6 +91,15 @@ benchmark {
9391
iterationTimeUnit = "ms"
9492
reportFormat = "csv" // csv report format
9593
}
94+
95+
fork {
96+
include("CommonBenchmark")
97+
iterations = 5
98+
iterationTime = 300
99+
iterationTimeUnit = "ms"
100+
advanced("jvmForks", "definedByJmh") // see README.md for possible "jvmForks" values
101+
advanced("nativeFork", "perIteration") // see README.md for possible "nativeFork" values
102+
}
96103
}
97104

98105
// Setup configurations

runtime/commonMain/src/kotlinx/benchmark/RunnerConfiguration.kt

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ class RunnerConfiguration(config: String) {
1010
init {
1111
println("Config:")
1212
println(config)
13-
13+
1414
println("Values:")
1515
println(values)
1616
}
@@ -33,7 +33,13 @@ class RunnerConfiguration(config: String) {
3333
val iterationTime = singleValueOrNull("iterationTime") { it.toLong() }
3434
val iterationTimeUnit = singleValueOrNull("iterationTimeUnit") { parseTimeUnit(it) }
3535

36-
val forks = singleValueOrNull("forks") { it.toInt() }
36+
val jvmForks = singleValueOrNull("jvmForks").let { forks ->
37+
val legacy = singleValueOrNull("forks")
38+
if (legacy != null) {
39+
println("""Deprecation warning: configuration option "forks" was renamed to "jvmForks"""")
40+
}
41+
forks ?: legacy
42+
}
3743

3844
val outputTimeUnit = singleValueOrNull(
3945
"outputTimeUnit"

runtime/jvmMain/src/kotlinx/benchmark/jvm/JvmBenchmarkRunner.kt

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,18 @@ fun main(args: Array<String>) {
4343

4444
val runtimeMXBean = ManagementFactory.getRuntimeMXBean()
4545
val jvmArgs = runtimeMXBean.inputArguments
46-
when {
47-
jvmArgs.any { it.contains("libasyncProfiler") } -> jmhOptions.forks(0)
48-
config.forks == null -> jmhOptions.forks(1)
49-
config.forks > 0 -> jmhOptions.forks(config.forks)
46+
if (jvmArgs.any { it.contains("libasyncProfiler") }) {
47+
jmhOptions.forks(0)
48+
} else {
49+
when (config.jvmForks) {
50+
null -> jmhOptions.forks(1)
51+
"definedByJmh" -> { /* do not override */ }
52+
else -> {
53+
val forks = config.jvmForks.toIntOrNull()?.takeIf { it >= 0 }
54+
?: throw IllegalArgumentException("jvmForks: expected a non-negative integer or \"definedByJmh\" string literal")
55+
jmhOptions.forks(forks)
56+
}
57+
}
5058
}
5159

5260
val reportFormat = ResultFormatType.valueOf(config.reportFormat.uppercase())

0 commit comments

Comments
 (0)