Hope that helps!
2,476 karma · joined June 18, 2009
Hope that helps!
At the time I'd sent the email I was unaware Ruby Together was on HN front page (and that's why people were pinging me)
Thanks dad.
https://gist.github.com/tenderlove/25853f50ab46a58738ff2cc22d682f2b
I ran both files through xxd then diffed them. I've literally changed every piece of hardware (at no small cost). "premature to immediately blame Apple" seems a bit off.Yes! People might do `map` transformations, but it's very common to do other stuff at the same time. Any other allocations during that transformation would ruin cache hit rate.
> At the same time, the callsite for any given `.new()` invocation will almost always be creating an instance of the exact same class. The target expression is nearly always just a constant name. That makes it a prime candidate for good inline caching at those callsites.
Yes again!
ZJIT is a method based JIT (the type of compiler traditionally taught in schools) where YJIT is a lazy basic block versioning (LBBV) compiler. We're using what we learned developing and deploying YJIT to build an even better JIT compiler. IOW we're going to fold some of YJIT's techniques in to ZJIT.
> And if so, will these YJIT features likes Fast Allocations be brought to ZJIT?
It may not have been clear from the post, but this fast allocation strategy is actually implemented in the byte code interpreter. You will get a speedup without using any JIT compiler. We've already ported this fast-path to YJIT and are in the midst of implementing it in ZJIT.
Ya, I really enjoy pattern matching. I think new language features just take a long time to percolate through the community. I remember when `->` was controversial, but that's the only way I write lambdas today. :D
That said, it would be really great if Pat (or someone besides me) published an update version of RUM
It's the former. Each bytecode is the handler address and every handler does a load + jump. There's no dispatch table (though there are compilation options that allow you to use a dispatch table, but I doubt anybody does that since you'd have to specifically opt in when you compile Ruby).
> Sure, the question is always about the dynamic frequency of such call sites. What kind of ICs does YARV use? Are monomorphic calls inlined?
In one of our production applications, the most popular inline cache sees over 300 different classes and ~600 shapes (this is only for instance variable reads, I haven't measured method calls yet but suspect it's similar).
The VM only has a monomorphic cache (YJIT generates polymorphic caches), and neither the VM nor the JIT do inlining right now.
YARV (Ruby's VM) is already direct threaded (using computed gotos), so there's no dispatch loop to eliminate. YARV is a stack based virtual machine, and the machine code that YJIT generates writes temporary values to the VM stack. In other words, it always spills temporaries to memory. We're actively working on keeping things in registers rather than spilling.
Ruby programs tend to be extremely polymorphic. It's not uncommon to see call sites with hundreds of different classes (and now that we've implemented object shapes, hundreds of object shapes). YJIT is not currently splitting or inlining, so we unfortunately encounter megamorphic sites more frequently than we'd like.
I'm sure there's more stuff but I hope this helps!
Seems like we need benchmarks for actual web workloads. :)
Yes, that is one of my goals. I'll be presenting this project at RubyConf and I hope that I can get the compiler to compile itself by then. Breaking the circular dependencies is somewhat tricky, and you'll see some frankly ridiculous code inside TenderJIT that is meant to break those cycles.