Skip to content

Commit 2709405

Browse files
Elena LepilkinaLepilkinaElena
authored andcommitted
Added nativeGCCollectMode setting to choose strategy of calling K/N GC
1 parent 1818322 commit 2709405

File tree

9 files changed

+40
-10
lines changed

9 files changed

+40
-10
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,9 @@ Available configuration options:
148148
* `mode` – "thrpt" for measuring operations per time, or "avgt" for measuring time per operation
149149
* `nativeIterationMode` – "external" for iterating in gradle in order to get correct Kotlin/Native runtime input in measurement,
150150
"internal" can be used if it's known that measured code have no calls in K/N runtime that can influence on measurement unrepeatedly.
151+
* `nativeGCCollectMode` – "iteration" to collect garbage after each measuring iteration,
152+
"auto"(default) for collecting garbage at the moments choosen by K/N compiler, time for each iteration could be very
153+
different then because of unpredictable call of GC.
151154
* `include("…")` – regular expression to include benchmarks with fully qualified names matching it, as a substring
152155
* `exclude("…")` – regular expression to exclude benchmarks with fully qualified names matching it, as a substring
153156
* `param("name", "value1", "value2")` – specify a parameter for a public mutable property `name` annotated with `@Param`

examples/kotlin-multiplatform/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ benchmark {
9999
iterationTimeUnit = "ms" // time in ms per iteration
100100
advanced("forks", 1)
101101
nativeIterationMode = "internal"
102+
nativeGCCollectMode = "iteration"
102103
}
103104

104105
csv {

plugin/main/src/kotlinx/benchmark/gradle/BenchmarkConfiguration.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ open class BenchmarkConfiguration(val extension: BenchmarksExtension, val name:
1010
var iterationTimeUnit: String? = null
1111
var mode: String? = null
1212
var nativeIterationMode: String? = null // TODO: where should warning about K/N specific of this parameter be shown?
13+
var nativeGCCollectMode: String? = null
1314
var outputTimeUnit: String? = null
1415
var reportFormat: String? = null
1516

plugin/main/src/kotlinx/benchmark/gradle/Utils.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ fun writeParameters(
9595
config.outputTimeUnit?.let { appendln("outputTimeUnit:$it") }
9696
config.mode?.let { appendln("mode:$it") }
9797
config.nativeIterationMode?.let { appendln("nativeIterationMode:$it") }
98+
config.nativeGCCollectMode?.let { appendln("nativeGCCollectMode:$it") }
9899

99100
config.includes.forEach {
100101
appendln("include:$it")

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,12 +157,12 @@ private class CsvBenchmarkReportFormatter(val delimiter: String) : BenchmarkRepo
157157

158158
}
159159

160-
object JsonBenchmarkReportFormatter : BenchmarkReportFormatter() {
160+
private object JsonBenchmarkReportFormatter : BenchmarkReportFormatter() {
161161

162162
override fun format(results: Collection<ReportBenchmarkResult>): String =
163163
results.joinToString(",", prefix = "[", postfix = "\n]", transform = this::format)
164164

165-
fun format(result: ReportBenchmarkResult): String =
165+
private fun format(result: ReportBenchmarkResult): String =
166166
"""
167167
{
168168
"benchmark" : "${result.benchmark.name}",
@@ -175,6 +175,7 @@ object JsonBenchmarkReportFormatter : BenchmarkReportFormatter() {
175175
${result.params.entries.joinToString(separator = ",\n ") { "\"${it.key}\" : \"${it.value}\"" }}
176176
},
177177
"nativeIterationMode" : "${result.config.nativeIterationMode.toText()}",
178+
"nativeGCCollectMode" : "${result.config.nativeGCCollectMode.toText()}",
178179
"primaryMetric" : {
179180
"score": ${result.score},
180181
"scoreError": ${result.error},

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ enum class NativeIterationMode {
2828
Internal, External
2929
}
3030

31+
enum class NativeGCCollectMode {
32+
Auto, Iteration
33+
}
34+
3135
@Target(AnnotationTarget.CLASS)
3236
expect annotation class OutputTimeUnit(val value: BenchmarkTimeUnit)
3337

@@ -67,6 +71,13 @@ fun NativeIterationMode.toText() = when (this) {
6771
else -> throw UnsupportedOperationException("$this is not supported")
6872
}
6973

74+
@Suppress("REDUNDANT_ELSE_IN_WHEN")
75+
fun NativeGCCollectMode.toText() = when (this) {
76+
NativeGCCollectMode.Auto -> "auto"
77+
NativeGCCollectMode.Iteration -> "iteration"
78+
else -> throw UnsupportedOperationException("$this is not supported")
79+
}
80+
7081
@Suppress("REDUNDANT_ELSE_IN_WHEN")
7182
fun BenchmarkTimeUnit.toMultiplier() = when (this) {
7283
BenchmarkTimeUnit.NANOSECONDS -> 1

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

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ class BenchmarkConfiguration private constructor(
77
val iterationTimeUnit: BenchmarkTimeUnit,
88
val outputTimeUnit: BenchmarkTimeUnit,
99
val mode: Mode,
10-
val nativeIterationMode: NativeIterationMode) {
10+
val nativeIterationMode: NativeIterationMode,
11+
val nativeGCCollectMode: NativeGCCollectMode) {
1112

1213
constructor(runner: RunnerConfiguration, suite: SuiteDescriptor<*>) : this(
1314
runner.iterations ?: suite.iterations,
@@ -16,13 +17,15 @@ class BenchmarkConfiguration private constructor(
1617
runner.iterationTimeUnit ?: suite.iterationTime.timeUnit,
1718
runner.outputTimeUnit ?: suite.outputTimeUnit,
1819
runner.mode ?: suite.mode,
19-
runner.nativeIterationMode ?: NativeIterationMode.External
20+
runner.nativeIterationMode ?: NativeIterationMode.External,
21+
runner.nativeGCCollectMode ?: NativeGCCollectMode.Auto
2022
)
2123

2224
override fun toString() =
2325
"iterations=$iterations, warmups=$warmups, iterationTime=$iterationTime, " +
2426
"iterationTimeUnit=${iterationTimeUnit.toText()}, outputTimeUnit=${outputTimeUnit.toText()}, " +
25-
"mode=${mode.toText()}, nativeIterationMode=${nativeIterationMode.toText()}"
27+
"mode=${mode.toText()}, nativeIterationMode=${nativeIterationMode.toText()}, " +
28+
"nativeGCCollectMode=${nativeGCCollectMode.toText()}"
2629

2730
companion object {
2831
fun parse(description: String): BenchmarkConfiguration {
@@ -38,7 +41,8 @@ class BenchmarkConfiguration private constructor(
3841
parseTimeUnit(getParameterValue("iterationTimeUnit")),
3942
parseTimeUnit(getParameterValue("outputTimeUnit")),
4043
getParameterValue("mode").toMode(),
41-
NativeIterationMode.valueOf(getParameterValue("nativeIterationMode").capitalize())
44+
NativeIterationMode.valueOf(getParameterValue("nativeIterationMode").capitalize()),
45+
NativeGCCollectMode.valueOf(getParameterValue("nativeGCCollectMode").capitalize())
4246
)
4347
}
4448
}

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ class RunnerConfiguration(config: String) {
7272
"nativeIterationMode"
7373
) { NativeIterationMode.valueOf(it.capitalize()) }
7474

75+
val nativeGCCollectMode = singleValueOrNull(
76+
"nativeGCCollectMode"
77+
) { NativeGCCollectMode.valueOf(it.capitalize()) }
78+
7579
override fun toString(): String {
7680
return """$name -> $reportFile ($traceFormat, $reportFormat)
7781
params: ${params.entries.joinToString(prefix = "{", postfix = "}") { "${it.key}: ${it.value}" }}
@@ -84,6 +88,7 @@ iterationTimeUnit: $iterationTimeUnit
8488
outputTimeUnit: $outputTimeUnit
8589
mode: $mode
8690
nativeIterationMode: $nativeIterationMode
91+
nativeGCCollectMode: $nativeGCCollectMode
8792
"""
8893
}
8994
}

runtime/nativeMain/src/kotlinx/benchmark/native/NativeExecutor.kt

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ class NativeExecutor(name: String, args: Array<out String>) : SuiteExecutor(name
104104
// Execute warmup
105105
val cycles = externalCyclesNumber ?: warmup(suite.name, benchmarkRun.config, instance, benchmark)
106106
DoubleArray(iterations) { iteration ->
107-
val nanosecondsPerOperation = measure(instance, benchmark, cycles)
107+
val nanosecondsPerOperation = measure(instance, benchmark, cycles, benchmarkRun.config.nativeGCCollectMode)
108108
val text = nanosecondsPerOperation.nanosToText(benchmarkRun.config.mode, benchmarkRun.config.outputTimeUnit)
109109
val iterationNumber = externalIterationNumber ?: iteration
110110
reporter.output(
@@ -204,7 +204,8 @@ class NativeExecutor(name: String, args: Array<out String>) : SuiteExecutor(name
204204
private fun <T> measure(
205205
instance: T,
206206
benchmark: BenchmarkDescriptor<T>,
207-
cycles: Int
207+
cycles: Int,
208+
nativeGCCollectMode: NativeGCCollectMode
208209
): Double {
209210
val executeFunction = benchmark.function
210211
var counter = cycles
@@ -214,7 +215,8 @@ class NativeExecutor(name: String, args: Array<out String>) : SuiteExecutor(name
214215
@Suppress("UNUSED_VARIABLE")
215216
val result = instance.executeFunction() // ignore result for now, but might need to consume it somehow
216217
}
217-
GC.collect()
218+
if (nativeGCCollectMode == NativeGCCollectMode.Iteration)
219+
GC.collect()
218220
val endTime = getTimeNanos()
219221
val time = endTime - startTime
220222
return time.toDouble() / cycles
@@ -241,7 +243,8 @@ class NativeExecutor(name: String, args: Array<out String>) : SuiteExecutor(name
241243
endTime = getTimeNanos()
242244
iterations++
243245
}
244-
GC.collect()
246+
if (config.nativeGCCollectMode == NativeGCCollectMode.Iteration)
247+
GC.collect()
245248
val time = endTime - startTime
246249
val metric = time.toDouble() / iterations // TODO: metric
247250
val sample = metric.nanosToText(config.mode, config.outputTimeUnit)

0 commit comments

Comments
 (0)