Something similar to Racket places or V8 isolates can be implemented and keep compatibility with C extensions expecting GIL. It just needs somebody to actually do the work of swapping out hundreds of global variable accesses in MRI using something like CIL.
Do you mean every thread would have its own place/isolate for executing C extensions?
I think one difficulty there is some global state in C extensions might expect to be truly process-global.
Also, how would you isolate global variables in the C extension? If the C extension is a dynamic library, it's typically only loaded once per process.
Maybe something like dlmopen() to load multiple copies of a native library would help, but it's not portable.
Yeah, this is a real problem. The PG gem, for example, uses some global variables.
IMHO the only way to do it is to add incremental parallelism which leaves the GIL in place. Racket has already shown a solid path here.
Guilds would have a major performance problem: can't allocate objects without GIL. It's also a tricky mental model and requires invasive changes to existing Ruby code to handle frozen objects.
Places don't share a heap so they don't need the GIL to allocate objects and have independent GC rather than global GC. It's a model which fits better with existing Ruby code. The GVL can be relaxed while executing Ruby and grabbed by native methods.
> Guilds would have a major performance problem: can't allocate objects without GIL.
Why not? It'd be possible to have TLABs, isn't it? But yes, GC would still be for all Guilds at once.
Racket places don't allow to share objects, only arrays of primitive types, which seems very restrictive. And Racket futures are even more restricted.
I'm not sure about Guilds since it's not there yet, but it already sounds closer to Ruby multithreading and more flexible to me from an usage point of view.
TLABs are definitely possible but it's increasing the implementation complexity.
Places are deliberately shared-nothing to reduce the implementation complexity and provide a simple model to the user. Process oriented code can be easily ported.
Porting something like a Sidekiq based worker using ActiveRecord to work inside a Guild where all access to shared objects needs to be frozen would be a nightmare.
With Racket Places you can share more complex types but it needs to be done via FFI. It doesn't prevent you from implementing a sharable connection pool or anything.