I know you probably have a ton of experience trying to deal with it, but I don't think there is anything wrong with C extensions. They do serve a purpose. The main benefit of C extensions is to bring existing native code into Ruby, but a solid FFI implementation could probably be better.
I think the general direction of MRI is to try and support some native bridging. But as always, compatibility is a concern.
indeed, we wrote a good FFI a decade ago, and time to do the second version of that integrated with the instruction set
I really admire your work, so basically, I think you should keep pushing forward with your ideas.
Koichi is probably reinventing your work right now then, because he is working on similar instructions within MRI - the ability to directly call C code.
thank you :) I'm really glad to see you around, I've been... elsewhere for a while (learned a ton about market research though)
(and minimise overhead with doing so, e.g. stack frames within MRI)
I think I should see if I can try to bridge the divide between what you are working on and MRI.
I know at times it can be frustrating.
MRI will adopt good Rubinius ideas in about 10 years, judging from history :D
it's beyond frustrating, but I'm not losing any sleep over it anymore
we should talk about IO and concurrency sometime
it's time to get those dialed-in in Rubinius
btw, the 1st gen Rubinius JIT could elide FFI overhead and emit direct calls to the C function
all that stuff is not particularly complex and we had it many many years ago
the frustrating thing is where we could be today, and what we could have built in those years, but instead I get to hear things about how much better Elixir or Node or Go etc is than Ruby
and that makes me :sad:
what are your thoughts on Crystal @brixen
Node and Go are not better than ruby
Crystal is cool, but Rubinius with a good JIT is cooler :)
how far off is a hard question (I cannot control all the inputs), but what needs to be done isn't complicated
the problem with the 1st gen JIT is that only Evan, I, Dirkjan, and an fresh CS grad when I was at Enova ever touched the code
and it was buggy, so that was a big problem
I completely rewrote the instruction set architecture, and I have a PoC of a tier-0 JIT that just linearizes the function calls (all the instructions are now simple C++ functions) with explicit flow control, hand that to LLVM to do some common opts, and emit the machine code
tier-1 would then use a not-complicated intermediate representation that would be able to do basic inlining
tier-2 would do type feedback and more aggressive inlining
we don't need type annotations for speed
also, since the 1st gen JIT, I've created the CodeDB, so we have a mechanism for type info persistence across process invocations
even the LLVM IR could be stored in the CodeDB for an ahead-of-time compiled version
which is probably the next step to speeding up boot time, since I lazy load (just-in-time) the bytecode of the core library
but there are still ~5000 methods executed just to load the core library
whereas in MRI, it's just the link loader patching some addresses
@mixflame anyway, lots of possibilities, but I'll look at JIT as soon as I can address the GC issues reliably
reading your article haha
Rubinius got booted from nokogiri's CI because of GC segvs (that may or may not be Rubinius' fault)
but I've had this discussion for a long time with nokogiri, mysql2 gem, bundler
it's easy to blame Rubinius, and I don't have enough evidence yet to say which are to blame, except the concurrency issues I filed with bundler