Skip to content

Commit

Permalink
Add benchmarking (#16)
Browse files Browse the repository at this point in the history
  • Loading branch information
05nelsonm authored Dec 18, 2024
1 parent 17ab18a commit 19809c8
Show file tree
Hide file tree
Showing 10 changed files with 635 additions and 335 deletions.
72 changes: 43 additions & 29 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,52 +6,29 @@ env:
GRADLE_OPTS: -Dorg.gradle.daemon=false -Dkotlin.incremental=false -Dorg.gradle.jvmargs="-XX:+HeapDumpOnOutOfMemoryError -XX:MetaspaceSize=1g"

jobs:
build:
check:
strategy:
fail-fast: false
matrix:
os: [ macos-latest, ubuntu-latest, windows-latest ]

runs-on: ${{ matrix.os }}

steps:
- name: Checkout Repo
uses: actions/checkout@v3
- name: Checkout Repository
uses: actions/checkout@v4

- name: Validate Gradle Wrapper
uses: gradle/wrapper-validation-action@v1

- name: Setup Caches [ Gradle Wrapper ]
uses: actions/cache@v1
with:
path: ~/.gradle/wrapper
key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('gradle/wrapper/gradle-wrapper.*') }}
restore-keys: ${{ runner.os }}-gradle-wrapper-

- name: Setup Caches [ Konan ]
uses: actions/cache@v1
with:
path: ~/.konan
key: ${{ runner.os }}-konan-${{ hashFiles('**/*.gradle.kts') }}-${{ hashFiles('gradle/libs.versions.toml') }}
restore-keys: ${{ runner.os }}-konan-

- name: Setup Caches [ Gradle Caches ]
uses: actions/cache@v1
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-caches-${{ hashFiles('**/*.gradle.kts') }}-${{ hashFiles('gradle/libs.versions.toml') }}
restore-keys: ${{ runner.os }}-gradle-caches-
uses: gradle/actions/wrapper-validation@v3

- name: Setup JDK
uses: actions/setup-java@v3.4.0
uses: actions/setup-java@v4
with:
distribution: 'zulu'
java-version: 11

- name: Check API Compatibility
if: matrix.os == 'macos-latest'
run: >
./gradlew check --stacktrace
./gradlew apiCheck --stacktrace
- name: Run macOS Tests
if: matrix.os == 'macos-latest'
Expand All @@ -70,3 +47,40 @@ jobs:
run: >
./gradlew check --stacktrace
-PKMP_TARGETS="JVM,JS,MINGW_X64,WASM_JS,WASM_WASI"
- name: Upload Test Reports
uses: actions/upload-artifact@v4
if: ${{ always() }}
with:
name: test-report-${{ matrix.os }}
path: '**/build/reports/tests/**'
retention-days: 1

benchmark:
strategy:
fail-fast: false
matrix:
os: [ macos-latest, ubuntu-latest, windows-latest ]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout Repository
uses: actions/checkout@v4

- name: Validate Gradle Wrapper
uses: gradle/actions/wrapper-validation@v3

- name: Setup JDK
uses: actions/setup-java@v4
with:
distribution: 'zulu'
java-version: 11

- name: Run Benchmark
run: >
./gradlew benchmark
- name: Upload Benchmark Reports
uses: actions/upload-artifact@v4
with:
name: benchmark-report-${{ matrix.os }}
path: '**/build/reports/benchmarks/**'
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
.idea/
*.iml
local.properties
.kotlin/
728 changes: 425 additions & 303 deletions .kotlin-js-store/yarn.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions benchmarks/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
build/
33 changes: 33 additions & 0 deletions benchmarks/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# benchmarks

Benchmarks for tracking performance of `sponges` implementation(s).

**NOTE:** Benchmarking is run on every Pull Request. Results can be viewed for each
workflow run on the [GitHub Actions][url-actions] tab of the repository.

- Run All platforms:
```shell
./gradlew benchmark
```

- Run Jvm:
```shell
./gradlew jvmBenchmark
```

- Run Js:
```shell
./gradlew jsBenchmark
```

- Run WasmJs:
```shell
./gradlew wasmJsBenchmark
```

- Run Native:
```shell
./gradlew nativeHostBenchmark
```

[url-actions]: https://github.com/KotlinCrypto/sponges/actions/
62 changes: 62 additions & 0 deletions benchmarks/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Copyright (c) 2024 Matthew Nelson
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
import io.matthewnelson.kmp.configuration.extension.container.target.KmpTarget
import kotlinx.benchmark.gradle.BenchmarksExtension
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
import org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalWasmDsl
import org.jetbrains.kotlin.konan.target.HostManager
import org.jetbrains.kotlin.konan.target.KonanTarget

plugins {
id("configuration")
}

kmpConfiguration {
val benchmarks by lazy { extensions.getByType<BenchmarksExtension>() }

@OptIn(ExperimentalWasmDsl::class)
configure {
fun <T: KotlinTarget> KmpTarget<T>.register() {
target { benchmarks.targets.register(name) }
}

jvm { register() }

js { target { browser(); nodejs() }; register() }
wasmJs { target { browser(); nodejs() }; register() }

val nativeHost = "nativeHost"
when (HostManager.host) {
is KonanTarget.LINUX_X64 -> linuxX64(nativeHost) { register() }
is KonanTarget.LINUX_ARM64 -> linuxArm64(nativeHost) { register() }
is KonanTarget.MACOS_X64 -> macosX64(nativeHost) { register() }
is KonanTarget.MACOS_ARM64 -> macosArm64(nativeHost) { register() }
is KonanTarget.MINGW_X64 -> mingwX64(nativeHost) { register() }
else -> {}
}

common {
pluginIds(libs.plugins.benchmark.get().pluginId)

sourceSetMain {
dependencies {
implementation(libs.benchmark.runtime)
implementation(project(":library:keccak"))
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright (c) 2024 Matthew Nelson
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
package org.kotlincrypto.sponges.benchmarks

import kotlinx.benchmark.*
import org.kotlincrypto.sponges.keccak.F1600
import org.kotlincrypto.sponges.keccak.KeccakP

@State(Scope.Benchmark)
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(BenchmarkTimeUnit.MILLISECONDS)
@Warmup(iterations = 5, time = 2)
@Measurement(iterations = 5, time = 4)
open class KeccakPBenchmark {

private val state = F1600()

@Setup
fun setup() {
repeat(21) { index -> state.addData(index, (index + 10).toLong()) }
}

@Benchmark
fun keccakP() { KeccakP(state) }
}
12 changes: 11 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
**/
import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnLockMismatchReport
import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnPlugin
import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnRootExtension

plugins {
alias(libs.plugins.benchmark) apply(false)
alias(libs.plugins.binary.compat)
alias(libs.plugins.kotlin.multiplatform) apply(false)
}
Expand All @@ -31,8 +33,14 @@ allprojects {
}
}

@Suppress("PropertyName")
val CHECK_PUBLICATION = findProperty("CHECK_PUBLICATION") != null

plugins.withType<YarnPlugin> {
the<YarnRootExtension>().lockFileDirectory = rootDir.resolve(".kotlin-js-store")
if (CHECK_PUBLICATION) {
the<YarnRootExtension>().yarnLockMismatchReport = YarnLockMismatchReport.NONE
}
}

apiValidation {
Expand All @@ -41,7 +49,9 @@ apiValidation {
@OptIn(kotlinx.validation.ExperimentalBCVApi::class)
klib.enabled = findProperty("KMP_TARGETS") == null

if (findProperty("CHECK_PUBLICATION") != null) {
if (CHECK_PUBLICATION) {
ignoredProjects.add("check-publication")
} else {
ignoredProjects.add("benchmarks")
}
}
7 changes: 5 additions & 2 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
[versions]
gradle-benchmark = "0.4.11"
gradle-binary-compat = "0.16.3"
gradle-kmp-configuration = "0.3.2"
gradle-kotlin = "1.9.24"
gradle-publish-maven = "0.29.0"

# tests
encoding = "2.2.2"
encoding = "2.3.1"
kotlincrypto-endians = "0.3.1"

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

# tests
# tests & tools
benchmark-runtime = { module = "org.jetbrains.kotlinx:kotlinx-benchmark-runtime", version.ref = "gradle-benchmark" }
encoding-base16 = { module = "io.matthewnelson.encoding:base16", version.ref = "encoding" }
kotlincrypto-endians-endians = { module = "org.kotlincrypto.endians:endians", version.ref = "kotlincrypto-endians" }

[plugins]
benchmark = { id = "org.jetbrains.kotlinx.benchmark", version.ref = "gradle-benchmark" }
binary-compat = { id = "org.jetbrains.kotlinx.binary-compatibility-validator", version.ref = "gradle-binary-compat" }
kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "gradle-kotlin" }
16 changes: 16 additions & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
/*
* Copyright (c) 2023 Matthew Nelson
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
rootProject.name = "sponges"

pluginManagement {
Expand All @@ -15,5 +30,6 @@ private val CHECK_PUBLICATION: String? by settings
if (CHECK_PUBLICATION != null) {
include(":tools:check-publication")
} else {
include(":benchmarks")
include(":library:keccak")
}

0 comments on commit 19809c8

Please sign in to comment.