diff --git a/benchmarks/build.gradle.kts b/benchmarks/build.gradle.kts index f64c4aaa21..222f13e22f 100644 --- a/benchmarks/build.gradle.kts +++ b/benchmarks/build.gradle.kts @@ -70,6 +70,7 @@ dependencies { implementation("com.typesafe.akka:akka-actor_2.12:2.5.0") implementation(project(":kotlinx-coroutines-core")) + implementation(project(":kotlinx-coroutines-debug")) implementation(project(":kotlinx-coroutines-reactive")) // add jmh dependency on main diff --git a/benchmarks/src/jmh/kotlin/benchmarks/debug/DebugProbesConcurrentBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/debug/DebugProbesConcurrentBenchmark.kt new file mode 100644 index 0000000000..4c1a67a4d0 --- /dev/null +++ b/benchmarks/src/jmh/kotlin/benchmarks/debug/DebugProbesConcurrentBenchmark.kt @@ -0,0 +1,71 @@ +/* + * Copyright 2016-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package benchmarks.debug + +import kotlinx.coroutines.* +import kotlinx.coroutines.debug.* +import org.openjdk.jmh.annotations.* +import org.openjdk.jmh.annotations.State +import java.util.concurrent.* + +@Warmup(iterations = 5, time = 1) +@Measurement(iterations = 5, time = 1) +@Fork(value = 1) +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +@State(Scope.Benchmark) +open class DebugProbesConcurrentBenchmark { + + @Setup + fun setup() { + DebugProbes.sanitizeStackTraces = false + DebugProbes.enableCreationStackTraces = false + DebugProbes.install() + } + + @TearDown + fun tearDown() { + DebugProbes.uninstall() + } + + + @Benchmark + fun run() = runBlocking { + var sum = 0L + repeat(8) { + launch(Dispatchers.Default) { + val seq = stressSequenceBuilder((1..100).asSequence()) { + (1..it).asSequence() + } + + for (i in seq) { + sum += i.toLong() + } + } + } + sum + } + + private fun stressSequenceBuilder(initialSequence: Sequence, children: (Node) -> Sequence): Sequence { + return sequence { + val initialIterator = initialSequence.iterator() + if (!initialIterator.hasNext()) { + return@sequence + } + val visited = HashSet() + val sequences = ArrayDeque>() + sequences.addLast(initialIterator.asSequence()) + while (sequences.isNotEmpty()) { + val currentSequence = sequences.removeFirst() + for (node in currentSequence) { + if (visited.add(node)) { + yield(node) + sequences.addLast(children(node)) + } + } + } + } + } +}