Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce jvmBenchmarks into kotlinx-coroutines-core #3946

Merged
merged 2 commits into from
Nov 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions kotlinx-coroutines-core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
* Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/

plugins {
id 'org.jetbrains.kotlinx.benchmark' version '0.4.9'
}

apply plugin: 'org.jetbrains.kotlin.multiplatform'
apply plugin: 'org.jetbrains.dokka'

Expand Down Expand Up @@ -167,6 +171,13 @@ kotlin {

// For animal sniffer
withJava()
compilations.create('benchmark') { associateWith(compilations.main) }
}
}

benchmark {
targets {
register("jvmBenchmark")
}
}

Expand Down
15 changes: 15 additions & 0 deletions kotlinx-coroutines-core/jvmBenchmark/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
## kotlinx-coroutines-core benchmarks

This source-set contains benchmarks that leverage `internal` API (e.g. `suspendCancellableCoroutineReusable`)
and thus cannot be written in `benchmarks` module.

This is an interim solution unless we introduce clear separation of responsibilities in benchmark modules
and decide on their usability.


### Usage

```
./gradlew :kotlinx-coroutines-core:jvmBenchmarkBenchmarkJar
java -jar kotlinx-coroutines-core/build/benchmarks/jvmBenchmark/jars/kotlinx-coroutines-core-jvmBenchmark-jmh-1.7.2-SNAPSHOT-JMH.jar
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/

package kotlinx.coroutines

import java.util.concurrent.*

public fun doGeomDistrWork(work: Int) {
// We use geometric distribution here. We also checked on macbook pro 13" (2017) that the resulting work times
// are distributed geometrically, see https://github.com/Kotlin/kotlinx.coroutines/pull/1464#discussion_r355705325
val p = 1.0 / work
val r = ThreadLocalRandom.current()
while (true) {
if (r.nextDouble() < p) break
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
/*
* Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
* Copyright 2016-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/

package benchmarks
package kotlinx.coroutines

import benchmarks.common.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlinx.coroutines.scheduling.*
Expand Down Expand Up @@ -80,8 +79,7 @@ open class SemaphoreBenchmark {
}

enum class SemaphoreBenchDispatcherCreator(val create: (parallelism: Int) -> CoroutineDispatcher) {
// FORK_JOIN({ parallelism -> ForkJoinPool(parallelism).asCoroutineDispatcher() }),
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
FORK_JOIN({ parallelism -> ForkJoinPool(parallelism).asCoroutineDispatcher() }),
DEFAULT({ parallelism -> ExperimentalCoroutineDispatcher(corePoolSize = parallelism, maxPoolSize = parallelism) })
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
/*
* Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
* Copyright 2016-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/

package benchmarks
package kotlinx.coroutines.channels

import benchmarks.common.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.scheduling.*
import kotlinx.coroutines.selects.select
import org.openjdk.jmh.annotations.*
import java.lang.Integer.max
import java.util.concurrent.ForkJoinPool
import java.util.concurrent.Phaser
import java.util.concurrent.TimeUnit

Expand Down Expand Up @@ -136,8 +136,7 @@ open class ChannelProducerConsumerBenchmark {
}

enum class DispatcherCreator(val create: (parallelism: Int) -> CoroutineDispatcher) {
//FORK_JOIN({ parallelism -> ForkJoinPool(parallelism).asCoroutineDispatcher() }),
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
FORK_JOIN({ parallelism -> ForkJoinPool(parallelism).asCoroutineDispatcher() }),
DEFAULT({ parallelism -> ExperimentalCoroutineDispatcher(corePoolSize = parallelism, maxPoolSize = parallelism) })
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/*
* Copyright 2016-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
* Copyright 2016-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/

package benchmarks.tailcall
package kotlinx.coroutines.channels

import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
/*
* Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
* Copyright 2016-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/

package benchmarks.tailcall
package kotlinx.coroutines.channels

import kotlinx.coroutines.*
import kotlin.coroutines.*
import kotlin.coroutines.intrinsics.*

@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
public abstract class SimpleChannel {
companion object {
const val NULL_SURROGATE: Int = -1
Expand Down Expand Up @@ -83,13 +82,11 @@ class CancellableChannel : SimpleChannel() {
}

class CancellableReusableChannel : SimpleChannel() {
@Suppress("INVISIBLE_MEMBER")
override suspend fun suspendReceive(): Int = suspendCancellableCoroutineReusable {
consumer = it.intercepted()
COROUTINE_SUSPENDED
}

@Suppress("INVISIBLE_MEMBER")
override suspend fun suspendSend(element: Int) = suspendCancellableCoroutineReusable<Unit> {
enqueuedValue = element
producer = it.intercepted()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/*
* Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
* Copyright 2016-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/

package benchmarks.tailcall
package kotlinx.coroutines.channels

import kotlinx.coroutines.*
import org.openjdk.jmh.annotations.*
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
/*
* Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
* Copyright 2016-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/

@file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")

package benchmarks.flow
package kotlinx.coroutines.flow

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.flow.internal.*
import kotlinx.coroutines.flow.internal.AbortFlowException
import kotlinx.coroutines.flow.internal.unsafeFlow
import org.openjdk.jmh.annotations.*
import java.util.concurrent.TimeUnit
import java.util.concurrent.*

@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
Expand Down