From: Charles Oliver Nutter Date: 2011-04-11T09:02:37+09:00 Subject: Re: Hash Surprises with Fixnum, #hash, and #eql? Top-replying with a general observation: you can't please everyone all the time. The special-cased logic for Fixnums and Symbols in hashes is obviously done for performance purposes. No matter what you do, checking for method redefinitions every single time will have a performance impact. Even checking an inline cache has an impact. When you look at how frequently hashes are used with Fixnum or Symbol keys, you'd basically be asking everyone to take a perf hit to do it the "right way" for a tiny minority of use cases. There are also plenty of other cases in all the implementations where modifying critical core classes does not get reflected during execution. For example, some impls treat operator calls against Fixnum as always being the Fixnum version, regardless of modifications. This allows using a fast type-identity check rather than a cache check or class-modification check, and it can make a *huge* difference for raw numeric performance. In this case I think there's a fine line between consistency and zealotry. The *vast* majority of Ruby users will never reopen and modify Fixnum or Symbol, so it's a 99%-safe assumption that "fast" logic for those types is just fine, especially if it's a noticeable perf boost for the 99% of users. We're talking about the lowest-level values in the system...if they can't be made fast, everything else suffers. JRuby follows MRI largely because of the perf improvement, but also partially because MRI does it this way. If MRI always dispatched, we'd do what we need to do to always dispatch (and we do have other ways internally to reduce -- but not eliminate -- the modification check). A side note on JRuby's optimization strategy over the years: 1. We find a largely-invariant piece of logic that could be optimized, like fixnum operators or hashes of symbols 2. We come up with an optimization that may diverge slightly from "pure" behavior and add an opt-in flag for that optimization 3. Based on user reports, test runs, and so on, we may eventually turn the optimization on all the time and make the flag be opt-out We've been more conservative than other impls, even. - Charlie On Fri, Apr 8, 2011 at 8:25 PM, Clifford Heath wrote: > On 04/08/11 20:12, Robert Klemme wrote: >> >> On Fri, Apr 8, 2011 at 9:30 AM, Clifford Heath  wrote: >>> >>> On 04/07/11 19:19, Robert Klemme wrote: >>>> >>>> On Thu, Apr 7, 2011 at 6:05 AM, Clifford Heath >>>>  wrote: >>>> I also doubt whether it is a good idea to allow for subclassing of an >>>> integer like class.  What use case do you have in mind which would >>>> make this necessary? >>> >>> What's wrong with the case you use in that blog post? >> >> You mean, make HexNum a subclass of Integer?  Yes, actually that's >> what I had attempted at the time but failed for technical reasons > > No, I don't mean making HexNum a subclass of Integer, but making it an > "integer like class" which can be subclassed. > >> (explained in the blog).  As it turns out it's generally not necessary >> to inherit Integer in Ruby to create a class which behaves like an >> integer (most of the time). > > Right. I'd like to see that work *more* of the time :). Or at least, > that each Ruby interpreter should fail in the same way. > >>> I suspect that you "doubt it is a good idea" only because Ruby's object >>> model for numbers is inconsistent, and you're defensive about that. >> >> Where exactly do you see the inconsistency?  I can see that a few >> things in that area do not match common expectations.  But I don't >> think it's really inconsistent. > > By inconsistent, I mean that Ruby doesn't make it possible to make > subclasses of Integer that play nicely with other Integers. Fixnum > and Bignum are mutually compatible and automatically and invisibly > convert back and forth, but it's not possible for an user's class to > do the same. That's inconsistent. A few more calls to coerce and some > more circumspect interpreter optimisations and it would all be pretty > ok. > > Note that I expect there will still be a need for Java-style boxed > and unboxed integer values. C# makes the boxing even more transparent > than Java,  but Ruby doesn't even try. > >> Your problem is not so much with numeric classes IMHO but rather with >> implementations of class Hash in different versions of Ruby.  Namely >> do they have issues treating instances from different class as >> equivalent. > > Yes. It's documented to use #hash and #eql?, so that's what it should do. > If it also has invisible optimisations, fine. So long as they're invisible. > >> Fixnum and Bignum do not share common values so you never have >> instances of different classes representing the same numeric integer >> value: > > Yes. But I never need to know where the cut-over is, and it can be different > with different Ruby build targets. It's almost completely transparent. > >> Apparently there are optimizations done under the hood (similarly to >> duping an unfrozen String as key) > > Except that the case of String is documented, and works the same in all > interpreters. > >> which is probably OK from a >> pragmatic point of view (what you attempt seems rather seldom done). > > Mainly because it doesn't work :) > > Clifford Heath. > >