-
Notifications
You must be signed in to change notification settings - Fork 188
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
A way to mark C extensions as thread-safe, so they can be executed in parallel #2136
Comments
There are two main places where we would need to fix things, when creating the stubs that wrap C methods, and when making calls into the Ruby runtime which would release and reacquire the lock. I think we can do this through a macro (call it |
I was thinking the main place where we take the lock is |
Given https://bugs.ruby-lang.org/issues/17307#note-21 rb_define_method(mod, "need C ext lock", func1, 0);
#ifdef HAVE_RB_EXT_THREAD_SAFE
rb_ext_thread_safe(true);
#endif
rb_define_method(mod, "does not need C ext lock and can run in parallel", func2, 0);
#ifdef HAVE_RB_EXT_THREAD_SAFE
rb_ext_thread_safe(false);
#endif
rb_define_method(mod, "need C ext lock", func3, 0); |
@ioquatix says a way to define it explicitly per method would be nice, like: rb_define_method(mod, "does not need C ext lock and can run in parallel", func2, RB_NO_EXT_LOCK(arity)); It's more verbose if many methods, but explicit vs implicit thread-local state. Maybe we can have both. |
Here is a way to efficiently pack flags into #include <limits.h>
const int MASK = 15;
const int NOGVL = 16; // space for ~26 more bit flags.
int combine(int count, int flags) {
if (count >= 0) return count | flags;
else return count & ~flags;
}
int count(int arity) {
if (arity & INT_MIN) {
return (arity | ~MASK);
} else {
return (arity & MASK);
}
}
int flags(int arity) {
if (arity & INT_MIN) {
return (~arity & ~MASK);
} else {
return (arity & ~MASK);
}
} |
The plan here is to not use the C extensions lock if |
Is there any progress on this issue? |
https://github.com/ruby/ruby/blob/993bb55d982f315f5137fc9b5d9d087e971270c2/doc/extension.rdoc#label-Appendix+F.+Ractor+support describes the conditions for It could be useful to also have a way to override the safe value for a given gem/extension, i.e. as if the Init_ function called |
Totally agree with the previous post, for situations like ruby/nkf#19 (comment), or for when gem maintainers just haven't responded even though we know for certain their C-extension is safe. I'd suggest a config file where we can just list the gems for which we want to assume their C-extension(s) are threadsafe, but any way of being able to do so, even if it was listing paths or Init function names would be great! |
We plan to work on this for the next release. |
TruffleRuby supports C extensions, but for scalability it is important to run at least some of them in parallel (e.g., HTTP parsing in Puma). This was notably mentioned in my RubyKaigi talk.
So we need a way to mark a given C extension as thread-safe, so we know we do not need to acquire a global lock when executing its methods.
More details on the MRI tracker: https://bugs.ruby-lang.org/issues/17307
Currently there is the experimental option
--cexts-lock=false
but that's global so safe only if we know all the extensions used are thread-safe.The text was updated successfully, but these errors were encountered: