Process, Mister. • Ruby can do multiple things at once. Not everything grabs the GVL. • "Free" activities include waiting on the database or network, plus many calculations performed by C Native Extensions. • Other than that, you get one activity per process.
on purpose. Matz wants threads to break only between lines of Ruby. • That requires a GVL. Matz is frequently quoted as hating threads and wishing he hadn't added them to Ruby. I'm not kidding.
and hard even for the pros. • How to avoid sync issues while allowing concurrency? • Erlang-style copying; most objects belong to one thread. • And that's how Ractors work.
per Ractor - every thread lives in a specific parent Ractor • Never use Ractors? You get the old behaviour. • Replace Threads with Ractors? You get full concurrency. • But how do they sync?
state (e.g. Random.) A lot of libraries will need restructuring. For now, you can't use them from non-primary Ractors*. • Never add a Ractor? You can ignore all of this. * "Is Rails going to support Ractors now?" Not soon. Any idea how much shared global state Rails has?
from N to N+99 are prime # and returns an integer bit-vector of the true/false results Ractor.new(pipe) do |pipe| while n = pipe.take bools = (n..(n+99)).map { |nn| nn.prime? } p_int = bools.inject(0) { |total, b| total * 2 + (b ? 1 : 0) } Ractor.yield [n, p_int ] end end This is the same benchmark code I use later, though I wrap it in slightly different Ractor read/write access patterns.
as N processes* (max speed at 100% CPU all cores.) • Ractors have implementation limits that slow them down. • With no memory limits, right now: Processes > Ractors > Threads in nearly all cases. * if memory isn't an important limit
occasional hangs. How's the speed on a 4-vCPU Linode? Not good. There are test benchmarks where Ractors work as claimed but I have trouble duplicating those results. Here's a small benchmark (5 workers, 1,000 msgs/worker) with several Ractor access patterns.
All calculation means threads are slower than single. Multiple processes ("fork") is fast b/c no GVL. All Ractor code does worse than threading, not better.
bad and ractors get better with more messages? Here we try 10 workers and 10,000 msgs/ worker (I skip "single" here, it's about the same as "thread.") Basically: not that much worse than threads, but never better than threads.
be some simple way to make this fast. But I tried a lot of things with no luck. • Ractors hang on reasonable-looking use cases and you can't use a lot of Ruby standard library code.
core benchmark code. That's how I got this far. • On a Mac they're even less stable. • The little printed warning about Ractors being experimental? They mean it.