Timeout with withTimeout in Kotlin - Time & Space Complexity
When using withTimeout in Kotlin, we want to understand how the program's running time changes as the input or task size grows.
We ask: How does the timeout affect the total work done before stopping?
Analyze the time complexity of the following code snippet.
import kotlinx.coroutines.*
suspend fun doWorkWithTimeout(time: Long) {
withTimeout(time) {
repeat(1000) { i ->
delay(10) // simulate work
println("Working on task $i")
}
}
}
This code tries to do 1000 small tasks, each taking 10ms, but stops if the total time exceeds the given timeout.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The
repeat(1000)loop that runs tasks. - How many times: Up to 1000 times, but may stop earlier if timeout occurs.
The number of tasks attempted depends on the timeout value. If the timeout is large, more tasks run; if small, fewer tasks run.
| Timeout (ms) | Approx. Tasks Completed |
|---|---|
| 100 | About 10 tasks |
| 5000 | About 500 tasks |
| 15000 | All 1000 tasks |
Pattern observation: The work done grows roughly linearly with the timeout until the maximum tasks are done.
Time Complexity: O(min(n, t/d))
This means the work grows with the smaller of the number of tasks n or the time limit t divided by the delay per task d.
[X] Wrong: "The loop always runs all 1000 tasks regardless of timeout."
[OK] Correct: The withTimeout stops the loop early if the time limit is reached, so fewer tasks may run.
Understanding how timeouts affect loops helps you reason about real-world programs that must stop work early to stay responsive or save resources.
What if we replaced delay(10) with a longer or shorter delay? How would the time complexity change?
Practice
withTimeout do?Solution
Step 1: Understand the purpose of withTimeout
withTimeoutis designed to stop a block of code if it exceeds a given time limit.Step 2: Compare options with the definition
Only "It stops a block of code if it runs longer than the specified time." correctly describes this behavior. Other options describe different coroutine behaviors.Final Answer:
It stops a block of code if it runs longer than the specified time. -> Option CQuick Check:
withTimeout stops code after time limit [OK]
- Confusing withTimeout with delay function
- Thinking it repeats code instead of stopping
- Assuming it cancels all coroutines globally
withTimeout in Kotlin?Solution
Step 1: Recall the function signature
The correct syntax uses parentheses with the timeout in milliseconds as the first argument, followed by a lambda block.Step 2: Match options with correct syntax
withTimeout(1000) { /* code block */ } matches this pattern exactly. Others use incorrect brackets or misplaced arguments.Final Answer:
withTimeout(1000) { /* code block */ } -> Option AQuick Check:
withTimeout uses parentheses for timeout [OK]
- Using square brackets instead of parentheses
- Placing timeout inside the block instead of argument
- Using colon instead of parentheses
import kotlinx.coroutines.*
fun main() = runBlocking {
try {
withTimeout(100) {
repeat(5) { i ->
println("Processing $i")
delay(50)
}
}
} catch (e: TimeoutCancellationException) {
println("Timeout occurred")
}
}Solution
Step 1: Analyze the timing of the loop and timeout
Each iteration delays 50ms. After two iterations, 100ms timeout is reached.Step 2: Determine output before timeout
"Processing 0" and "Processing 1" print before timeout triggers. Then exception is caught and "Timeout occurred" prints.Final Answer:
Processing 0 Processing 1 Timeout occurred -> Option BQuick Check:
Timeout stops after 2 prints + exception message [OK]
- Assuming all iterations print before timeout
- Ignoring exception catch block
- Thinking timeout cancels immediately without partial output
withTimeout:
import kotlinx.coroutines.*
fun main() = runBlocking {
withTimeout(100) {
delay(200)
println("Done")
}
}Solution
Step 1: Understand withTimeout behavior with delay
The delay of 200ms exceeds the 100ms timeout, causing a TimeoutCancellationException.Step 2: Check error handling
No try-catch is present, so exception will be thrown and program will crash.Final Answer:
TimeoutCancellationException is thrown because delay exceeds timeout. -> Option AQuick Check:
Delay longer than timeout causes exception [OK]
- Assuming code waits full delay then prints
- Thinking try-catch is mandatory syntax
- Believing delay can't be used inside withTimeout
withTimeout to achieve this and handle timeout gracefully?Solution
Step 1: Understand correct placement of withTimeout and try-catch
The timeout should wrap the networkRequest call, and the exception should be caught outside to handle timeout.Step 2: Evaluate options for proper structure
try { withTimeout(500) { networkRequest() } } catch (e: TimeoutCancellationException) { println("Request timed out") } correctly wraps networkRequest inside withTimeout and catches the exception outside. withTimeout(500) { try { networkRequest() } catch (e: TimeoutCancellationException) { println("Request timed out") } } catches inside, which won't catch timeout. withTimeoutOrNull(500) { networkRequest() } ?: println("Request timed out") uses withTimeoutOrNull (valid but different). try { networkRequest() withTimeout(500) } catch (e: TimeoutCancellationException) { println("Request timed out") } misplaces withTimeout after networkRequest.Final Answer:
try { withTimeout(500) { networkRequest() } } catch (e: TimeoutCancellationException) { println("Request timed out") } -> Option DQuick Check:
Wrap withTimeout around call, catch outside [OK]
- Catching exception inside withTimeout block
- Placing withTimeout after the call
- Confusing withTimeout with withTimeoutOrNull
Ready to prove it?
Pass the test and this pattern moves unknown
