I’ve toyed around with Ractors, thinking they might be a Godsend for GUI apps, like those built by Glimmer DSL for LibUI (https://github.com/AndyObtiva/glimmer-dsl-libui). But, they always turned out to be more pain to use with the variable access restrictions than plain old threads, which I get for free as truly parallel in JRuby while using Glimmer DSL for SWT (https://github.com/AndyObtiva/glimmer-dsl-swt).

I don’t know. Maybe one day I’ll see the light of Ractors and change my mind, but being a long time multithreading user, I always thought the fears of using true multithreading were overblown in Ruby to the point of impracticality. In actuality, I use multithreading all the time when building desktop apps, and I never have issues with deadlocks given I correctly use mutexes/semaphores, or given that many apps don’t even need to share data through the threads, but could benefit from threads for parallel processing. It would be nice to have the more convenient  option of multithreading for those cases at least. 

I’ve always thought Ruby’s stance on multithreading was extreme. why not support it behind a non-default switch, and let those who don’t fear using them and know how to benefit from them safely use real multithreading by passing a switch, instead of getting forced to use something very restrictive and inconvenient like Ractors. 

But, if it were my decision, I’d even make multithreading always enabled in Ruby. I’ve built countless desktop GUI apps with JRuby’s multithreading support over the years, and never had any issues. Check out this Mandelbrot Fractal renderer that takes advantage of all your CPU cores! 
https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/docs/reference/GLIMMER_SAMPLES.md#mandelbrot-fractal

I’ve observed that most people who have issues with multithreading don’t really have a solid foundation of parallel concurrent programming from a university degree (I have a BSc in CS), reading books, or real experience, and thus misunderstand how to build multithreaded apps, thus run into the problems they claim are horrifying to the point of discouraging multithreading. 

Exhibit A: the Mandelbrot Fractal problem. Some people assume that given that you want to calculate fractal pixels in a grid, you’d have to have a thread per pixel. Wrong!!! You are supposed to have as many thread as your CPU core threads only, and distribute work to them in a pool. They won’t share data, so there won’t be a deadlock. But, people weak in parallel concurrent programming will try to use a thread per pixel and even share a data structure between all of them, and then will tell you that true multithreading is too memory consuming and dangerous, and will end up cursing threads and wanting to use fibers or ractors instead. Well, that’s because of their inexperience in how to write parallel code correctly with threads to begin with more than anything. As a result, everybody is suffering an impractical restriction in Ruby because a few bad programmers don’t know how to do multithreading when in fact it’s a simple matter of practice makes perfect. 

I’d rather we follow the true Ruby way, which is to empower programmers with freedom (like the freedom of dynamic typing) and leaving them be responsible adults. So, multithreading should have the same Ruby way freedom too. It’s no different. And, at minimum, provide a Ruby command switch for truly parallel multithreading to those who know what they’re doing. 

Andy Maleh

On Sat, Jan 21, 2023 at 9:37 AM Lionel Bouton via ruby-talk <ruby-talk@ml.ruby-lang.org> wrote:
Hi,

I just evaluated the possibility of using Ractors to distribute
processing using various gems with native extensions (some matrix/vector
computations with Numo::Linalg and approximate vector searches) and I've
mixed feelings.

The Ractor design seems very sound to me and I would prefer to use them
to distribute the load on multiple CPUs but in practice I see 2 major
obstacles :
- the first use of Ractor code isn't encouraging, even with Ruby 3.2.0,
as it outputs :
"warning: Ractor is experimental, and the behavior may change in future
versions of Ruby! Also there are many implementation issues."
- when heavy computations are involved you are probably already using
gems with native extensions and when trying to use them in a non-main
Ractor you will almost always get an exception :
"ractor unsafe method called from not main ractor (Ractor::UnsafeError)"

This last problem could be manageable, according to :
https://bugs.ruby-lang.org/issues/17307
native extensions should mark their individual functions as thread safe
using :

#ifdef HAVE_RB_EXT_RACTOR_SAFE
   rb_ext_ractor_safe(true);
#endif

I was considering contacting the maintainers of the various gems that we
use to check with them which methods are safe and to see if I can submit
a pull request but I'm a bit hesitant and wonders if Ractors are
actually used and stable enough for maintainers to care.

Do people on this list use Ractors? What for?
Do people code gems with native extensions with them in mind? I've seen
traces of rb_ext_ractor_safe when searching on Github but almost all of
the matches are from load.h from the Ruby headers but not many actual
uses (in the 4 first pages of results Psych and TruffleRuby are the only
exceptions and the first external gem is ruby-extlz4 on the 5th page...).

I've yet to see how the ffi gem can handle Ractors, I already know
there's no trace of Ractors in its code and this could be a complete new
can of worms (or not...).

I'll dig a bit more but in my current position I think I'll favor a
multi-process solution to scale (mostly because I don't have a
definitive list of gems I'll have to patch at this point and time is
short). That's a shame and I'm willing to revisit this later.

Best regards,

Lionel
 ______________________________________________
 ruby-talk mailing list -- ruby-talk@ml.ruby-lang.org
 To unsubscribe send an email to ruby-talk-leave@ml.ruby-lang.org
 ruby-talk info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-talk.ml.ruby-lang.org/
--