Skip to content

Commit

Permalink
Add kotlinx benchmark (#50)
Browse files Browse the repository at this point in the history
* Update README.md

* Add gradle toolchains resolver

* Add kotlinx benchmark
  • Loading branch information
MohamedRejeb committed May 27, 2024
1 parent 4897af3 commit 5f07e79
Show file tree
Hide file tree
Showing 8 changed files with 231 additions and 32 deletions.
4 changes: 3 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
plugins {
id("root.publication")
alias(libs.plugins.multiplatform).apply(false)
alias(libs.plugins.kotlin.multiplatform).apply(false)
alias(libs.plugins.kotlin.allopen).apply(false)
alias(libs.plugins.kotlinx.kover).apply(false)
alias(libs.plugins.kotlinx.benchmark).apply(false)
}

allprojects {
Expand Down
7 changes: 6 additions & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
[versions]
kotlin = "2.0.0"
kotlinx-kover = "0.8.0"
kotlinx-benchmark = "0.4.10"

nexus-publish = "2.0.0"

[libraries]
nexus-publish = { module = "io.github.gradle-nexus.publish-plugin:io.github.gradle-nexus.publish-plugin.gradle.plugin", version.ref = "nexus-publish" }

kotlinx-benchmark-runtime = { module = "org.jetbrains.kotlinx:kotlinx-benchmark-runtime", version.ref = "kotlinx-benchmark" }

[plugins]
multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
kotlin-allopen = { id = "org.jetbrains.kotlin.plugin.allopen", version.ref = "kotlin" }
kotlinx-kover = { id = "org.jetbrains.kotlinx.kover", version.ref = "kotlinx-kover" }
kotlinx-benchmark = { id = "org.jetbrains.kotlinx.benchmark", version.ref = "kotlinx-benchmark" }
20 changes: 19 additions & 1 deletion kotlin-js-store/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ balanced-match@^1.0.0:
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==

benchmark@*:
version "2.1.4"
resolved "https://registry.yarnpkg.com/benchmark/-/benchmark-2.1.4.tgz#09f3de31c916425d498cc2ee565a0ebf3c2a5629"
integrity sha512-l9MlfN4M1K/H2fbhfMy3B7vJd6AGKJVQn2h6Sg/Yx+KckoUA7ewS5Vv6TjSq18ooE1kS9hhAlQRH3AkXIh/aOQ==
dependencies:
lodash "^4.17.4"
platform "^1.3.3"

binary-extensions@^2.0.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
Expand Down Expand Up @@ -281,6 +289,11 @@ locate-path@^6.0.0:
dependencies:
p-locate "^5.0.0"

lodash@^4.17.4:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==

[email protected]:
version "4.1.0"
resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503"
Expand Down Expand Up @@ -375,6 +388,11 @@ picomatch@^2.0.4, picomatch@^2.2.1:
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==

platform@^1.3.3:
version "1.3.6"
resolved "https://registry.yarnpkg.com/platform/-/platform-1.3.6.tgz#48b4ce983164b209c2d45a107adb31f473a6e7a7"
integrity sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==

randombytes@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"
Expand Down Expand Up @@ -406,7 +424,7 @@ [email protected]:
dependencies:
randombytes "^2.1.0"

[email protected]:
source-map-support@*, source-map-support@0.5.21:
version "0.5.21"
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f"
integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==
Expand Down
144 changes: 144 additions & 0 deletions ksoup-benchmark/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
import kotlinx.benchmark.gradle.JsBenchmarkTarget
import kotlinx.benchmark.gradle.JsBenchmarksExecutor
import kotlinx.benchmark.gradle.JvmBenchmarkTarget

plugins {
alias(libs.plugins.kotlin.multiplatform)
alias(libs.plugins.kotlin.allopen)
alias(libs.plugins.kotlinx.benchmark)
}

allOpen {
annotation("org.openjdk.jmh.annotations.State")
}

kotlin {
applyDefaultHierarchyTemplate()

jvm {
val mainCompilation = compilations["main"]
compilations.create("benchmark") { associateWith(mainCompilation) }
}
js(IR) {
nodejs()
val mainCompilation = compilations["main"]
compilations.create("defaultExecutor") { associateWith(mainCompilation) }
compilations.create("builtInExecutor") { associateWith(mainCompilation) }
}
@OptIn(org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalWasmDsl::class)
wasmJs().nodejs()

// Native targets
iosX64()
iosArm64()
iosSimulatorArm64()
macosX64()
macosArm64()
linuxX64()
linuxArm64()
mingwX64()

sourceSets.commonMain.dependencies {
implementation(projects.ksoupEntities)
implementation(projects.ksoupHtml)

implementation(libs.kotlinx.benchmark.runtime)
}

sourceSets.jsMain {
sourceSets["jsDefaultExecutor"].dependsOn(this)
sourceSets["jsBuiltInExecutor"].dependsOn(this)
}
}

// Configure benchmark
benchmark {
configurations {
named("main") { // --> jvmBenchmark, jsBenchmark, <native target>Benchmark, benchmark
iterations = 5 // number of iterations
iterationTime = 300
iterationTimeUnit = "ms"
advanced("jvmForks", 3)
advanced("jsUseBridge", true)
}

register("params") {
iterations = 5 // number of iterations
iterationTime = 300
iterationTimeUnit = "ms"
include("ParamBenchmark")
param("data", 5, 1, 8)
param("unused", 6, 9)
}

register("fast") { // --> jvmFastBenchmark, jsFastBenchmark, <native target>FastBenchmark, fastBenchmark
include("Common")
exclude("long")
iterations = 5
iterationTime = 300 // time in ms per iteration
iterationTimeUnit = "ms" // time in ms per iteration
advanced("nativeGCAfterIteration", true)
}

register("csv") {
include("Common")
exclude("long")
iterations = 1
iterationTime = 300
iterationTimeUnit = "ms"
reportFormat = "csv" // csv report format
}

register("fork") {
include("CommonBenchmark")
iterations = 5
iterationTime = 300
iterationTimeUnit = "ms"
advanced("jvmForks", "definedByJmh") // see README.md for possible "jvmForks" values
advanced("nativeFork", "perIteration") // see README.md for possible "nativeFork" values
}
}

// Setup configurations
targets {
// This one matches target name, e.g. 'jvm', 'js',
// and registers its 'main' compilation, so 'jvm' registers 'jvmMain'
register("jvm") {
this as JvmBenchmarkTarget
jmhVersion = "1.21"
}
// This one matches source set name, e.g. 'jvmMain', 'jvmTest', etc
// and register the corresponding compilation (here the 'benchmark' compilation declared in the 'jvm' target)
register("jvmBenchmark") {
this as JvmBenchmarkTarget
jmhVersion = "1.21"
}
register("jsDefaultExecutor")
register("jsBuiltInExecutor") {
this as JsBenchmarkTarget
jsBenchmarksExecutor = JsBenchmarksExecutor.BuiltIn
}
register("wasmJs")

// Native targets
register("iosX64")
register("iosArm64")
register("iosSimulatorArm64")
register("macosX64")
register("macosArm64")
register("linuxX64")
register("linuxArm64")
register("mingwX64")
}
}

// Node.js with canary v8 that supports recent Wasm GC changes
rootProject.extensions.findByType<org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension>()?.apply {
version = "21.0.0-v8-canary202309167e82ab1fa2"
downloadBaseUrl = "https://nodejs.org/download/v8-canary"
}

// Drop this when node js version become stable
configure(rootProject.tasks.withType(org.jetbrains.kotlin.gradle.targets.js.npm.tasks.KotlinNpmInstallTask::class)) {
args.add("--ignore-engines")
}
37 changes: 37 additions & 0 deletions ksoup-benchmark/src/commonMain/kotlin/benchmark/CommonBenchmark.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package benchmark

import com.mohamedrejeb.ksoup.html.parser.KsoupHtmlHandler
import com.mohamedrejeb.ksoup.html.parser.KsoupHtmlParser
import kotlinx.benchmark.*

@State(Scope.Benchmark)
@Measurement(iterations = 3, time = 1, timeUnit = BenchmarkTimeUnit.SECONDS)
@OutputTimeUnit(BenchmarkTimeUnit.MILLISECONDS)
@BenchmarkMode(Mode.AverageTime)
class CommonBenchmark {
private lateinit var handler: KsoupHtmlHandler
private lateinit var parser: KsoupHtmlParser

@Setup
fun setUp() {
handler = KsoupHtmlHandler
.Builder()
.build()
parser = KsoupHtmlParser(handler = handler)
}

@TearDown
fun teardown() {
parser.end()
}

@Benchmark
fun parseHtml() {
parser.write("<html><head><title>Test</title></head><body><h1>Test</h1></body></html>")
}

@Benchmark
fun parseComplexAndLongHtml() {
parser.write("<html><head><title>Test</title><style>body { color: red; }</style><script>console.log('test')</script></head><body><!-- comment --><h1 class='title' id='test'>Test</h1></body></html>".repeat(100))
}
}
22 changes: 8 additions & 14 deletions ksoup-entities/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
plugins {
alias(libs.plugins.multiplatform)
alias(libs.plugins.kotlin.multiplatform)
id("module.publication")
}

Expand Down Expand Up @@ -35,19 +35,13 @@ kotlin {
@OptIn(org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalWasmDsl::class)
wasmWasi().nodejs()

sourceSets {
/* Main source sets */
val commonMain by getting {
dependencies {
// The library is lightweight, we don't use any other dependencies :D
}
}
/* Main source sets */
sourceSets.commonMain.dependencies {
// The library is lightweight, we don't use any other dependencies :D
}

/* Test source sets */
val commonTest by getting {
dependencies {
implementation(kotlin("test"))
}
}
/* Test source sets */
sourceSets.commonTest.dependencies {
implementation(kotlin("test"))
}
}
24 changes: 9 additions & 15 deletions ksoup-html/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
plugins {
alias(libs.plugins.multiplatform)
alias(libs.plugins.kotlin.multiplatform)
id("module.publication")
}

Expand Down Expand Up @@ -35,20 +35,14 @@ kotlin {
@OptIn(org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalWasmDsl::class)
wasmWasi().nodejs()

sourceSets {
/* Main source sets */
val commonMain by getting {
dependencies {
implementation(project(":ksoup-entities"))
// The library is lightweight, we don't use any other dependencies :D
}
}
/* Main source sets */
sourceSets.commonMain.dependencies {
implementation(projects.ksoupEntities)
// The library is lightweight, we don't use any other dependencies :D
}

/* Test source sets */
val commonTest by getting {
dependencies {
implementation(kotlin("test"))
}
}
/* Test source sets */
sourceSets.commonTest.dependencies {
implementation(kotlin("test"))
}
}
5 changes: 5 additions & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
rootProject.name = "Ksoup"

enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")

pluginManagement {
includeBuild("convention-plugins")
repositories {
Expand All @@ -24,4 +26,7 @@ plugins {
include(
":ksoup-html",
":ksoup-entities",

// Benchmark module
":ksoup-benchmark",
)

0 comments on commit 5f07e79

Please sign in to comment.