Skip to content

Commit 7a70cff

Browse files
committed
Add a sequential semaphore benchmark and a generalized version of ChannelSinkBenchmark that supports buffered channels and pre-allocates elements.
Signed-off-by: Nikita Koval <[email protected]>
1 parent a21b17d commit 7a70cff

File tree

2 files changed

+80
-0
lines changed

2 files changed

+80
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Copyright 2016-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package benchmarks
6+
7+
import kotlinx.coroutines.*
8+
import kotlinx.coroutines.channels.*
9+
import org.openjdk.jmh.annotations.*
10+
import java.util.concurrent.*
11+
import kotlin.coroutines.*
12+
13+
@Warmup(iterations = 3, time = 1)
14+
@Measurement(iterations = 5, time = 1)
15+
@BenchmarkMode(Mode.AverageTime)
16+
@OutputTimeUnit(TimeUnit.MILLISECONDS)
17+
@State(Scope.Benchmark)
18+
@Fork(1)
19+
open class ChannelSinkNoAllocationsBenchmark {
20+
private val unconfined = Dispatchers.Unconfined
21+
22+
@Benchmark
23+
fun channelPipeline(): Int = runBlocking {
24+
run(unconfined)
25+
}
26+
27+
private suspend inline fun run(context: CoroutineContext): Int {
28+
var size = 0
29+
Channel.range(context).consumeEach { size++ }
30+
return size
31+
}
32+
33+
private fun Channel.Factory.range(context: CoroutineContext) = GlobalScope.produce(context) {
34+
for (i in 0 until 100_000)
35+
send(Unit) // no allocations
36+
}
37+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package benchmarks
6+
7+
import kotlinx.coroutines.*
8+
import kotlinx.coroutines.sync.*
9+
import org.openjdk.jmh.annotations.*
10+
import java.util.concurrent.TimeUnit
11+
import kotlin.test.*
12+
13+
@Warmup(iterations = 5, time = 1)
14+
@Measurement(iterations = 10, time = 1)
15+
@BenchmarkMode(Mode.AverageTime)
16+
@OutputTimeUnit(TimeUnit.MILLISECONDS)
17+
@State(Scope.Benchmark)
18+
@Fork(1)
19+
open class SequentialSemaphoreAsMutexBenchmark {
20+
val s = Semaphore(1)
21+
22+
@Benchmark
23+
fun benchmark() : Unit = runBlocking {
24+
val s = Semaphore(permits = 1, acquiredPermits = 1)
25+
var step = 0
26+
launch(Dispatchers.Unconfined) {
27+
repeat(N) {
28+
assertEquals(it * 2, step)
29+
step++
30+
s.acquire()
31+
}
32+
}
33+
repeat(N) {
34+
assertEquals(it * 2 + 1, step)
35+
step++
36+
s.release()
37+
}
38+
}
39+
}
40+
41+
fun main() = SequentialSemaphoreAsMutexBenchmark().benchmark()
42+
43+
private val N = 1_000_000

0 commit comments

Comments
 (0)