aboutsummaryrefslogtreecommitdiffstats
path: root/benchmarks/src/jmh/kotlin/benchmarks/CancellableContinuationBenchmark.kt
blob: 99c0f04902d70c4472c2124f6797b839c989b87f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
/*
 * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
 */

package benchmarks

import kotlinx.coroutines.*
import org.openjdk.jmh.annotations.*
import java.util.concurrent.*
import kotlin.coroutines.*
import kotlin.coroutines.intrinsics.*

@Warmup(iterations = 5)
@Measurement(iterations = 10)
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
@State(Scope.Benchmark)
@Fork(2)
open class CancellableContinuationBenchmark {

    @Benchmark
    fun awaitWithSuspension(): Int {
        val deferred = CompletableDeferred<Int>()
        return run(allowSuspend = true) { deferred.await() }
    }

    @Benchmark
    fun awaitNoSuspension(): Int {
        val deferred = CompletableDeferred(1)
        return run { deferred.await() }
    }

    private fun run(allowSuspend: Boolean = false, block: suspend () -> Int): Int {
        val value = block.startCoroutineUninterceptedOrReturn(EmptyContinuation)
        if (value === COROUTINE_SUSPENDED) {
            if (!allowSuspend) {
                throw IllegalStateException("Unexpected suspend")
            } else {
                return -1
            }
        }

        return value as Int
    }

    object EmptyContinuation : Continuation<Int> {
        override val context: CoroutineContext
            get() = EmptyCoroutineContext

        override fun resumeWith(result: Result<Int>) {
        }
    }
}