Skip to content

Commit 326167d

Browse files
authored
Add benchmarks (#26)
1 parent 1a44666 commit 326167d

9 files changed

Lines changed: 652 additions & 358 deletions

File tree

.github/workflows/CI.yml

Lines changed: 45 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -6,44 +6,21 @@ env:
66
GRADLE_OPTS: -Dorg.gradle.daemon=false -Dkotlin.incremental=false -Dorg.gradle.jvmargs="-XX:+HeapDumpOnOutOfMemoryError -XX:MetaspaceSize=1g"
77

88
jobs:
9-
build:
9+
check:
1010
strategy:
1111
fail-fast: false
1212
matrix:
1313
os: [ macos-latest, ubuntu-latest, windows-latest ]
14-
1514
runs-on: ${{ matrix.os }}
16-
1715
steps:
18-
- name: Checkout Repo
19-
uses: actions/checkout@v3
16+
- name: Checkout Repository
17+
uses: actions/checkout@v4
2018

2119
- name: Validate Gradle Wrapper
22-
uses: gradle/wrapper-validation-action@v1
23-
24-
- name: Setup Caches [ Gradle Wrapper ]
25-
uses: actions/cache@v1
26-
with:
27-
path: ~/.gradle/wrapper
28-
key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('gradle/wrapper/gradle-wrapper.*') }}
29-
restore-keys: ${{ runner.os }}-gradle-wrapper-
30-
31-
- name: Setup Caches [ Konan ]
32-
uses: actions/cache@v1
33-
with:
34-
path: ~/.konan
35-
key: ${{ runner.os }}-konan-${{ hashFiles('**/*.gradle.kts') }}-${{ hashFiles('gradle/libs.versions.toml') }}
36-
restore-keys: ${{ runner.os }}-konan-
37-
38-
- name: Setup Caches [ Gradle Caches ]
39-
uses: actions/cache@v1
40-
with:
41-
path: ~/.gradle/caches
42-
key: ${{ runner.os }}-gradle-caches-${{ hashFiles('**/*.gradle.kts') }}-${{ hashFiles('gradle/libs.versions.toml') }}
43-
restore-keys: ${{ runner.os }}-gradle-caches-
20+
uses: gradle/actions/wrapper-validation@v3
4421

4522
- name: Setup JDK
46-
uses: actions/setup-java@v3.4.0
23+
uses: actions/setup-java@v4
4724
with:
4825
distribution: 'zulu'
4926
java-version: 11
@@ -57,16 +34,54 @@ jobs:
5734
if: matrix.os == 'macos-latest'
5835
run: >
5936
./gradlew check --stacktrace
60-
-PKMP_TARGETS="JVM,JS,IOS_ARM64,IOS_X64,IOS_SIMULATOR_ARM64,MACOS_ARM64,MACOS_X64,TVOS_ARM64,TVOS_X64,TVOS_SIMULATOR_ARM64,WATCHOS_ARM32,WATCHOS_ARM64,WATCHOS_DEVICE_ARM64,WATCHOS_X64,WATCHOS_SIMULATOR_ARM64,WASM_JS,WASM_WASI"
37+
-PKMP_TARGETS="IOS_ARM64,IOS_X64,IOS_SIMULATOR_ARM64,JVM,JS,MACOS_ARM64,MACOS_X64,TVOS_ARM64,TVOS_X64,TVOS_SIMULATOR_ARM64,WATCHOS_ARM32,WATCHOS_ARM64,WATCHOS_DEVICE_ARM64,WATCHOS_X64,WATCHOS_SIMULATOR_ARM64,WASM_JS,WASM_WASI"
6138
6239
- name: Run Linux Tests
6340
if: matrix.os == 'ubuntu-latest'
6441
run: >
6542
./gradlew check --stacktrace
66-
-PKMP_TARGETS="JVM,JS,ANDROID,ANDROID_ARM32,ANDROID_ARM64,ANDROID_X64,ANDROID_X86,LINUX_ARM64,LINUX_X64,WASM_JS,WASM_WASI"
43+
-PKMP_TARGETS="ANDROID,ANDROID_ARM32,ANDROID_ARM64,ANDROID_X64,ANDROID_X86,JVM,JS,LINUX_ARM64,LINUX_X64,WASM_JS,WASM_WASI"
6744
6845
- name: Run Windows Tests
6946
if: matrix.os == 'windows-latest'
7047
run: >
7148
./gradlew check --stacktrace
7249
-PKMP_TARGETS="JVM,JS,MINGW_X64,WASM_JS,WASM_WASI"
50+
51+
- name: Upload Test Reports
52+
uses: actions/upload-artifact@v4
53+
if: ${{ always() }}
54+
with:
55+
name: test-report-${{ matrix.os }}
56+
path: '**/build/reports/tests/**'
57+
retention-days: 1
58+
59+
benchmark:
60+
strategy:
61+
fail-fast: false
62+
matrix:
63+
os: [ macos-latest, ubuntu-latest, windows-latest ]
64+
runs-on: ${{ matrix.os }}
65+
steps:
66+
- name: Checkout Repository
67+
uses: actions/checkout@v4
68+
69+
- name: Validate Gradle Wrapper
70+
uses: gradle/actions/wrapper-validation@v3
71+
72+
- name: Setup JDK
73+
uses: actions/setup-java@v4
74+
with:
75+
distribution: 'zulu'
76+
java-version: 11
77+
78+
- name: Run Benchmark
79+
run: >
80+
./gradlew benchmark
81+
-PKMP_TARGETS="JVM,JS,LINUX_ARM64,LINUX_X64,MACOS_ARM64,MACOS_X64,MINGW_X64,WASM_JS,WASM_WASI"
82+
83+
- name: Upload Benchmark Reports
84+
uses: actions/upload-artifact@v4
85+
with:
86+
name: benchmark-report-${{ matrix.os }}
87+
path: '**/build/reports/benchmarks/**'

.kotlin-js-store/yarn.lock

Lines changed: 439 additions & 315 deletions
Large diffs are not rendered by default.

benchmarks/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
build/

benchmarks/README.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# benchmarks
2+
3+
<!-- TODO: CryptoRand Issue #23 -->
4+
Benchmarks for tracking performance of `SecureRandom` implementation.
5+
6+
**NOTE:** Benchmarking is run on every Pull Request. Results can be viewed for each
7+
workflow run on the [GitHub Actions][url-actions] tab of the repository.
8+
9+
- Run All platforms:
10+
```shell
11+
./gradlew benchmark
12+
```
13+
14+
- Run Jvm:
15+
```shell
16+
./gradlew jvmBenchmark
17+
```
18+
19+
- Run Js:
20+
```shell
21+
./gradlew jsBenchmark
22+
```
23+
24+
- Run WasmJs:
25+
```shell
26+
./gradlew wasmJsBenchmark
27+
```
28+
29+
- Run Native:
30+
```shell
31+
./gradlew nativeHostBenchmark
32+
```
33+
34+
<!-- TODO: CryptoRand Issue #23 -->
35+
[url-actions]: https://github.com/KotlinCrypto/secure-random/actions/

benchmarks/build.gradle.kts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* Copyright (c) 2025 Matthew Nelson
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
**/
16+
import io.matthewnelson.kmp.configuration.extension.container.target.KmpTarget
17+
import kotlinx.benchmark.gradle.BenchmarksExtension
18+
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
19+
import org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalWasmDsl
20+
import org.jetbrains.kotlin.konan.target.HostManager
21+
import org.jetbrains.kotlin.konan.target.KonanTarget
22+
23+
plugins {
24+
id("configuration")
25+
}
26+
27+
kmpConfiguration {
28+
val benchmarks by lazy { extensions.getByType<BenchmarksExtension>() }
29+
30+
@OptIn(ExperimentalWasmDsl::class)
31+
configure {
32+
fun <T: KotlinTarget> KmpTarget<T>.register() {
33+
target { benchmarks.targets.register(name) }
34+
}
35+
36+
jvm { register() }
37+
38+
js { target { browser(); nodejs() }; register() }
39+
wasmJs { target { browser(); nodejs() }; register() }
40+
41+
val nativeHost = "nativeHost"
42+
when (HostManager.host) {
43+
is KonanTarget.LINUX_X64 -> linuxX64(nativeHost) { register() }
44+
is KonanTarget.LINUX_ARM64 -> linuxArm64(nativeHost) { register() }
45+
is KonanTarget.MACOS_X64 -> macosX64(nativeHost) { register() }
46+
is KonanTarget.MACOS_ARM64 -> macosArm64(nativeHost) { register() }
47+
is KonanTarget.MINGW_X64 -> mingwX64(nativeHost) { register() }
48+
else -> {}
49+
}
50+
51+
common {
52+
pluginIds(libs.plugins.benchmark.get().pluginId)
53+
54+
sourceSetMain {
55+
dependencies {
56+
implementation(libs.benchmark.runtime)
57+
// TODO: :library:secure-random Issue #22
58+
implementation(project(":secure-random"))
59+
}
60+
}
61+
}
62+
}
63+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Copyright (c) 2025 Matthew Nelson
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
**/
16+
@file:Suppress("unused")
17+
18+
package org.kotlincrypto.benchmarks
19+
20+
import kotlinx.benchmark.*
21+
import org.kotlincrypto.SecureRandom
22+
23+
@State(Scope.Benchmark)
24+
@BenchmarkMode(Mode.AverageTime)
25+
@OutputTimeUnit(BenchmarkTimeUnit.NANOSECONDS)
26+
@Warmup(iterations = 5, time = 2)
27+
@Measurement(iterations = 5, time = 3)
28+
open class SecureRandomBenchmark {
29+
30+
private val buf = ByteArray(20)
31+
32+
@Setup
33+
fun setup() {
34+
SECURE_RANDOM.nextBytesCopyTo(buf)
35+
}
36+
37+
@Benchmark
38+
fun nextBytesCopyTo() {
39+
SECURE_RANDOM.nextBytesCopyTo(buf)
40+
}
41+
42+
private companion object {
43+
private val SECURE_RANDOM = SecureRandom()
44+
}
45+
}

build.gradle.kts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnPlugin
1717
import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnRootExtension
1818

1919
plugins {
20+
alias(libs.plugins.benchmark) apply(false)
2021
alias(libs.plugins.binary.compat)
2122
alias(libs.plugins.kotlin.multiplatform) apply(false)
2223
}
@@ -44,6 +45,7 @@ apiValidation {
4445
if (findProperty("CHECK_PUBLICATION") != null) {
4546
ignoredProjects.add("check-publication")
4647
} else {
48+
ignoredProjects.add("benchmarks")
4749
ignoredProjects.add("sample")
4850
}
4951
}

gradle/libs.versions.toml

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,22 @@
11
[versions]
2-
gradle-binary-compat = "0.16.3"
3-
gradle-kmp-configuration = "0.3.2"
4-
gradle-kotlin = "1.9.24"
5-
gradle-publish-maven = "0.29.0"
2+
gradle-benchmark = "0.4.11"
3+
gradle-binary-compat = "0.16.3"
4+
gradle-kmp-configuration = "0.3.2"
5+
gradle-kotlin = "1.9.24"
6+
gradle-publish-maven = "0.29.0"
67

7-
# tests
8-
kotlinx-coroutines = "1.8.1"
8+
kotlinx-coroutines = "1.8.1"
99

1010
[libraries]
11-
gradle-kmp-configuration = { module = "io.matthewnelson:gradle-kmp-configuration-plugin", version.ref = "gradle-kmp-configuration" }
12-
gradle-kotlin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "gradle-kotlin" }
13-
gradle-publish-maven = { module = "com.vanniktech:gradle-maven-publish-plugin", version.ref = "gradle-publish-maven" }
11+
gradle-kmp-configuration = { module = "io.matthewnelson:gradle-kmp-configuration-plugin", version.ref = "gradle-kmp-configuration" }
12+
gradle-kotlin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "gradle-kotlin" }
13+
gradle-publish-maven = { module = "com.vanniktech:gradle-maven-publish-plugin", version.ref = "gradle-publish-maven" }
1414

1515
# tests
16-
kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlinx-coroutines" }
16+
benchmark-runtime = { module = "org.jetbrains.kotlinx:kotlinx-benchmark-runtime", version.ref = "gradle-benchmark" }
17+
kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlinx-coroutines" }
1718

1819
[plugins]
19-
binary-compat = { id = "org.jetbrains.kotlinx.binary-compatibility-validator", version.ref = "gradle-binary-compat" }
20-
kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "gradle-kotlin" }
20+
benchmark = { id = "org.jetbrains.kotlinx.benchmark", version.ref = "gradle-benchmark" }
21+
binary-compat = { id = "org.jetbrains.kotlinx.binary-compatibility-validator", version.ref = "gradle-binary-compat" }
22+
kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "gradle-kotlin" }

settings.gradle.kts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,13 @@ private val CHECK_PUBLICATION: String? by settings
1515
if (CHECK_PUBLICATION != null) {
1616
include(":tools:check-publication")
1717
} else {
18-
include(":secure-random")
18+
listOf(
19+
"secure-random",
20+
).forEach { name ->
21+
// TODO: :library Issue #22
22+
include(":$name")
23+
}
24+
25+
include(":benchmarks")
1926
include(":sample")
2027
}

0 commit comments

Comments
 (0)