2 minutes
Leveraging Ractors for Parallelism in Ruby
Introduction
Ruby 3.0 introduced Ractors, Ruby’s approach to parallelism by isolating state and avoiding the Global Interpreter Lock (GIL). They behave like actors in other languages, passing messages instead of sharing memory. In this post we’ll cover:
- How Ractors isolate state
- Communicating via Channels
- Best practices and gotchas
- A benchmark comparing Ractors, Threads, and Fibers
What Are Ractors?
Ractors are Ruby’s native parallel abstraction. Each Ractor runs in its own thread and cannot directly access another Ractor’s local variables, preventing data races.
r = Ractor.new do
# This runs in a separate OS thread
5.times.map { |i| i * i }
end
result = r.take # => [0, 1, 4, 9, 16]
State isolation means you pass data through Channels rather than sharing objects.
Communicating with Channels
Channels let Ractors send and receive messages safely.
r1 = Ractor.new do
msg = Ractor.receive
Ractor.yield "Got: #{msg.upcase}"
end
r2 = Ractor.new do
r1.send "hello"
r1.take
end
puts r2.take # => "Got: HELLO"
Channels enforce immutability or copy-on-send for Ruby objects.
Best Practices and Gotchas
- Avoid shared mutable objects: Pass immutable data only.
- Watch out for copy costs: Large objects get copied between Ractors.
- Error handling: Exceptions in Ractors don’t bubble up; you must handle them inside.
r = Ractor.new do
begin
raise "Oops"
rescue => e
Ractor.yield "Error: #{e.message}"
end
end
puts r.take # => "Error: Oops"
Benchmark: Ractor vs Thread vs Fiber
Let’s compare computing prime numbers up to 50_000 in parallel: splitting the range into chunks and processing them concurrently.
Model | Time (ms) |
---|---|
Ractor | 1200 |
Thread | 1800 |
Fiber | 1500 |
(Numbers are illustrative; your mileage may vary based on workload and Ruby implementation.)
Conclusion
Ractors offer a clean, thread-safe way to leverage multiple cores in Ruby. While they require copy-on-send disciplines and careful error handling, they shine in CPU-bound tasks. Next time you hit a GIL bottleneck, give Ractors a try!