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.

ModelTime (ms)
Ractor1200
Thread1800
Fiber1500

(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!