RunBlocking for bridging in Kotlin - Time & Space Complexity
We want to understand how the time needed to run code changes when using runBlocking in Kotlin.
Specifically, how does waiting for coroutines inside runBlocking affect the total time?
Analyze the time complexity of the following code snippet.
import kotlinx.coroutines.*
fun main() = runBlocking {
repeat(5) { i ->
launch {
delay(100L)
println("Task $i done")
}
}
}
This code runs 5 coroutines inside runBlocking, each delaying 100 milliseconds before printing.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Launching 5 coroutines inside a loop.
- How many times: The loop runs 5 times, launching 5 separate tasks.
Each coroutine waits for a fixed delay, but they run at the same time inside runBlocking.
| Input Size (n) | Approx. Operations |
|---|---|
| 5 | 5 coroutines launched, total delay ~100ms |
| 10 | 10 coroutines launched, total delay ~100ms |
| 100 | 100 coroutines launched, total delay ~100ms |
Pattern observation: The total time stays about the same because coroutines run concurrently, not one after another.
Time Complexity: O(1)
The number of coroutines grows linearly with n (O(n)), but due to concurrency the total execution time remains constant O(1).
[X] Wrong: "All coroutines inside runBlocking run one after another, so total time is delay times number of coroutines."
[OK] Correct: Coroutines launched inside runBlocking run concurrently, so delays overlap and total time is closer to the longest single delay, not the sum.
Understanding how runBlocking manages coroutine execution helps you explain concurrency concepts clearly and shows you know how to bridge blocking and non-blocking code.
What if we replaced launch with async and awaited each result sequentially? How would the time complexity change?