Thanks Kris, good to know. As much as instanceof checks are usually a code smell, it sure would be nice if the interface version could be optimized somewhat (at least for shallow hierarchies).
Cheers Sent from my phone On May 24, 2012 10:41 PM, "Krystal Mok" <rednaxel...@gmail.com> wrote: > Hi Mike, > > On Fri, May 25, 2012 at 10:12 AM, Mike Duigou <mike.dui...@oracle.com>wrote: > >> >> On May 24 2012, at 16:32 , Vitaly Davidovich wrote: >> >> > That's a bit odd as I thought the Klass object in the VM stored >> something like 7 supers, which includes interfaces (if I'm not mistaken). >> I know that instanceof checks against final classes are optimized into a >> simple cmp against an address, but I'm surprised that a check against an >> interface for classes in a very shallow type hierarchy is up to x25 slower. >> Do you know why that is Mike? Did you ask the compiler guys by chance? >> > >> I didn't actually look much further into it other than to write a small >> microbenchmark to make sure it was the instanceof check. I tested a couple >> of different configs of classes and interfaces and supers. I was able to >> validate that 'x instanceof String' was as fast as 'x.getClass() == >> String.class' and that other cases were slower. Inheritance checks seemed >> faster than checks on interfaces. That was enough to tell me that I was on >> the wrong track with 'x instanceof Hashable' as a way to determine which >> hash algorithm to use. At least for C2 server compiler. >> >> FYI, "x.getClass() == String.class" will be just as fast when 7170463 [1] > is in. > > @Vitaly > > The fast subtype checking algorithm in HotSpot treats interfaces as > "secondary supers", which goes through a slow path. The super type display > in instanceKlass is only for "primary supers", which does not include > interfaces for instance classes. You may want to check out the details in > this paper [2]. > > > Definition 5: A class T is a secondary type iff T is an interface or > > an array of a secondary type. Every type is either a primary > > type or a secondary type but not both. > > Regards, > Kris > > [1]: > http://mail.openjdk.java.net/pipermail/hotspot-compiler-dev/2012-May/007730.html > [2]: http://dl.acm.org/citation.cfm?id=583821 > > >> If there is a thorough exploration or explanation of which dispatching >> techniques have good performance and an explanation of which idioms will >> never be fast I'd be interested to read it. >> >> Mike >> > Thanks >> > >> > Sent from my phone >> > >> > On May 24, 2012 5:26 PM, "Mike Duigou" <mike.dui...@oracle.com> wrote: >> > >> > On May 23 2012, at 16:31 , David Holmes wrote: >> > >> > > On 24/05/2012 2:24 AM, Mike Duigou wrote: >> > >> Hi Mike; >> > >> >> > >> The problem with using instanceof Hashable32 is that is much slower >> (often more than 25X) than instanceof String. It's slow enough that we >> won't reasonably consider using instanceof Hashable32 in JDK 8. We have >> considered making Object implement Hashable32 and add a virtual extension >> method to Object for hash32(). The extension method would just call >> hashCode(). A compiler that supports extension methods is not yet part of >> the JDK mainline repo yet (It is still in the Lambda repo). This approach >> would mean that we can avoid an instanceof check but there is a *lot* of >> entirely reasonable reservations about having Object implement an interface >> and gain a new method. >> > > >> > > Is it worth using: >> > > >> > > && (k instanceof String || k instanceof Hash32) >> > > >> > > to deal with that. What would be the penalty on non-String Hash32's? >> > >> > The problem in this case would be the k instances that are neither >> String nor Hash32. They would be severely impacted. Using Doug Lea's >> "loops" Map microbenchmark, "k instanceof Hash32" was up to 25 times more >> expensive than calling "k instanceof String". I suspect that it could be >> even higher with classes that have deep inheritance hierarchies. My >> non-Hash32 keys were all instances of Number (Float, Double, Integer and >> Long) so each had a single interface. >> > >> > Mike >> > >> > > David >> > > >> > >> Opinions and insights welcome, >> > >> >> > >> Mike >> > >> >> > >> On May 23 2012, at 00:38 , Mike Skells wrote: >> > >> >> > >>> Hi Mike, >> > >>> >> > >>> I have a query, why is this implementation limitted to String? >> > >>> Is this by intent? >> > >>> >> > >>> in HashMap the patch for hash calculation is >> > >>> 290 final int hash(Object k) { >> > >>> 291 int h = hashMask; >> > >>> 292 if ((0 != h)&& (k instanceof String)) { >> > >>> 293 return h ^ ((String)k).hash32(); >> > >>> .... >> > >>> whereas I would have thought that it should be >> > >>> 290 final int hash(Object k) { >> > >>> 291 int h = hashMask; >> > >>> 292 if ((0 != h)&& (k instanceof Hash32)) { >> > >>> 293 return h ^ ((Hash32)k).hash32(); >> > >>> .... >> > >>> >> > >>> As a more flexible improvement could you supply a HashCode and >> Equals delegate, and then the user can supply either a custom delegate, >> suitable for that application (e.g.one that iterates through array content, >> or any other application data structure that needs to be handled >> differently like c# uses >> http://msdn.microsoft.com/en-us/library/system.collections.iequalitycomparer) >> > >>> >> > >>> Regards >> > >>> >> > >>> Mike >> > >> >> > >> >> >