Hi,
Le 21/01/2023 à 23:23, Andy Maleh via ruby-talk a écrit :
[...]
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.
If you are referring to true concurrent threading, from what I know the
explanation is mostly library support. For example PHP as an ecosystem
took ages to truly support multi-threading (I'm not even sure it fully
does today) because most of the libraries built with it where designed
before it supported threads so they didn't support them (chicken and egg
problem).
It was far easier for Java to do it right as true concurrent threads
were baked in from the start.
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.
Yes if you only use pure Ruby or wrappers around Java libs. But unless
I'm mistaken interfacing JRuby with native C libraries is not
straightforward and certainly not thread safe by default: I don't see a
way around knowing which functions are safe and which aren't to properly
wrap/use them.
To properly support concurrent multi-threading in MRI with native
extensions you'd have to only expose thread-safe functions or advise how
to protect unsafe ones. You might have to rb_ext_ractor_safe(true) or
use something similar to manage this to avoid using trial and error to
see what fails.
Ractors are just another tool in the box.
- Threads are the obvious match when giving access to your whole state
to many concurrent executions is needed (can be motivated by the actual
problem to solve or the speed it gives for large amounts of information
transfer).
- Ractors are great when you want to divide your problem into portions
of code with very clear and concise interfaces. This promotes simplicity
which greatly helps when you need robustness (simplicity often
indirectly helps performance too).
- Whole processes are another tool that can be even more robust when
used properly: many Unix daemons (like Postfix, Apache in prefork mode,
PostgreSQL to name a few I use regularly) have been very solid in part
because they divide their work amongst re-startable processes with
clearly delimited responsibilities. This is the path we have taken until
now and will probably continue with although there's an expected slight
performance disadvantage with our new components.
Ractors seem to be victims of the same chicken and egg problem PHP
threads had. They are a good solution for a whole class of problems but
it seems almost nobody supports them and so they aren't as useful as
they could be.
If at least the interface wasn't experimental anymore, there might be
more incentive to work on making gems with native extensions Ractor
aware. At least this is how I see it: I'm tempted to fork some gems and
submit pull requests later after testing but this involves probably
several days of work for our needs and this experimental state is a risk
of our work going to waste. The whole process route is less risky right now.
Best regards,
--
Lionel Bouton
gérant de JTEK SARL
https://www.linkedin.com/in/lionelbouton/