Fiber for cooperative concurrency in Ruby - Time & Space Complexity
When using Fibers for cooperative concurrency, we want to understand how the program's running time changes as we switch between tasks.
We ask: How does the number of Fiber switches affect the total work done?
Analyze the time complexity of the following Ruby code using Fibers.
fiber1 = Fiber.new do
3.times do |i|
puts "Fiber1: step #{i}"
Fiber.yield
end
end
fiber2 = Fiber.new do
3.times do |i|
puts "Fiber2: step #{i}"
Fiber.yield
end
end
while fiber1.alive? || fiber2.alive?
fiber1.resume if fiber1.alive?
fiber2.resume if fiber2.alive?
end
This code runs two Fibers that take turns running steps, yielding control back and forth.
Look for loops and repeated Fiber switches.
- Primary operation: The loop that resumes each Fiber until both finish.
- How many times: Each Fiber runs 3 times, so total of 6 resumes and yields combined.
Imagine increasing the number of steps each Fiber runs.
| Input Size (steps per Fiber) | Approx. Operations (Fiber resumes) |
|---|---|
| 10 | 20 (2 Fibers x 10 steps) |
| 100 | 200 (2 Fibers x 100 steps) |
| 1000 | 2000 (2 Fibers x 1000 steps) |
Pattern observation: The total operations grow linearly with the number of steps per Fiber.
Time Complexity: O(n)
This means the total work grows directly in proportion to the number of steps each Fiber performs.
[X] Wrong: "Using Fibers makes the program run faster automatically."
[OK] Correct: Fibers help organize work cooperatively but do not reduce the total amount of work done; they just switch tasks without parallel speedup.
Understanding how Fibers manage work step-by-step helps you explain cooperative multitasking and its impact on program flow and performance.
What if we added more Fibers running concurrently? How would the time complexity change?
Practice
Fiber in Ruby?Solution
Step 1: Understand Fiber's role
Fibers allow manual pausing and resuming of code execution, enabling cooperative multitasking.Step 2: Differentiate from threads
Unlike threads, Fibers do not run in parallel automatically; they require explicit control.Final Answer:
To pause and resume tasks manually for cooperative multitasking -> Option AQuick Check:
Fiber = manual pause/resume [OK]
- Confusing Fibers with threads or parallelism
- Thinking Fibers run automatically in background
- Assuming Fibers speed up CPU usage
Solution
Step 1: Recall Fiber creation syntax
Ruby usesFiber.newwith a block to create a new Fiber.Step 2: Check other options
Methods likecreate,start, orrundo not exist for Fiber creation.Final Answer:
fiber = Fiber.new { puts 'Hello' } -> Option BQuick Check:
Fiber creation = Fiber.new [OK]
- Using non-existent Fiber methods like create or start
- Forgetting to pass a block to Fiber.new
- Confusing Fiber with Thread syntax
fiber = Fiber.new do puts 'Step 1' Fiber.yield puts 'Step 2' end fiber.resume puts 'Between' fiber.resume
Solution
Step 1: Trace first resume call
Callingfiber.resumeruns untilFiber.yield, printing 'Step 1'.Step 2: Trace code after first resume
After yield, control returns to main, printing 'Between'.Step 3: Trace second resume call
Secondfiber.resumeresumes after yield, printing 'Step 2'.Final Answer:
Step 1 Between Step 2 -> Option DQuick Check:
Fiber.yield pauses, resume continues [OK]
- Assuming all code runs at first resume
- Confusing order of prints around yield
- Thinking yield stops Fiber permanently
fiber = Fiber.new do puts 'Start' Fiber.yield puts 'End' end fiber.yield fiber.resume
Solution
Step 1: Check where Fiber.yield is called
The code callsfiber.yieldoutside the Fiber block, which is invalid.Step 2: Understand Fiber.yield usage
Fiber.yieldis a class method to pause current Fiber, not an instance method on Fiber objects.Final Answer:
Calling Fiber.yield outside a Fiber block causes an error -> Option AQuick Check:
Fiber.yield only inside Fiber block [OK]
- Calling fiber.yield instead of Fiber.yield
- Expecting Fiber.resume before yield call
- Thinking Fiber.new needs parameters for yield
fiber1 = Fiber.new do
3.times do |i|
puts "Fiber1: #{i}"
Fiber.yield
end
end
fiber2 = Fiber.new do
3.times do |i|
puts "Fiber2: #{i}"
Fiber.yield
end
end
while fiber1.alive? || fiber2.alive?
fiber1.resume if fiber1.alive?
fiber2.resume if fiber2.alive?
endSolution
Step 1: Understand Fiber alternation
Each Fiber prints a number then yields, pausing itself.Step 2: Trace the while loop
The loop resumes fiber1 then fiber2 alternately while they are alive.Step 3: Follow output order
Output alternates: Fiber1:0, Fiber2:0, Fiber1:1, Fiber2:1, Fiber1:2, Fiber2:2.Final Answer:
Fiber1: 0 Fiber2: 0 Fiber1: 1 Fiber2: 1 Fiber1: 2 Fiber2: 2 -> Option CQuick Check:
Fibers alternate resume and yield [OK]
- Assuming one Fiber runs completely before the other
- Mixing order of Fiber resumes
- Forgetting Fiber.yield pauses execution
Ready to prove it?
Pass the test and this pattern moves unknown
