Did you try it with -server? The server compiler has different thresholds for inlining as well as differing heuristics (it can speculatively inline with a guard). I'm wondering if what you're seeing is really the result of GC. Perhaps by fiddling with GC parameters (pick a really big young generation), you can see if the Iterator allocations are at fault.
There is definately a difference between calling Iterator.next() and list.get() With Iterator, you've got double polymorphic dispatch, first to List.iterator(), and then in the returned iterator implementation, a call to AbstractList.get(). Whereas, with List.get() you've got a single polymorphic dispatch, and a better chance that Hotspot might figure out the concrete type and inline it to foo[index]. The downside of course, is you lose for-each as well as slightly higher chance of range overflows. Is it possible to isolate further where this 3% boost comes from, so that rather than chance every instance of Iterator to integer loops, you only need to change the few giving the biggest problems. It's a real shame that the Java collections in this day and age still impose such performance overhead. -Ray On Fri, Jun 5, 2009 at 8:16 PM, Daniel Rice (דניאל רייס)<[email protected]> wrote: > It would not be easy to force all of these lists to have some > particular concrete implementation ("FinalArrayList") although some > could. I can repeat the analysis with a larger number of runs just to > be sure, but the speedup was seen in the context of the actual > compiler rather than a microbenchmark, so I believe there is some > reality to it. > > Dan > > On Thu, Jun 4, 2009 at 11:58 PM, Ray Cromwell<[email protected]> wrote: >> This test is invalid due to the way Class Hierarchy Analysis works in >> Hotspot (similar to type-tightening in GWT). Since you never touch any >> other List implementations, Hotspot will know that List == ArrayList >> and all method calls are monomorphic. Try adding a LinkedList to your >> test and see what happens. In JDK5 this would foul up the >> optimizations. In a complex case like the compiler, it's bound to >> pick up other implementations of list, even if it's just >> Collections.unmodifiableList(). >> >> Microbenchmarking Hotspot is never really effective and fraught with >> problems. You also might want to try the -server JVM flag which >> sometimes makes a huge difference. >> >> -Ray >> >> >> On Fri, Jun 5, 2009 at 6:35 AM, Amit Manjhi <[email protected]> wrote: >>> I completely agree with Scott here. It's hard to believe that there will be >>> a consistent 3% improvement just by using an explicit index. The change is >>> very much compiler/JVM dependent. And even if there were the case currently, >>> the next compiler/JVM could very easily fix this. >>> >>> Since I was surprised by the result, I wrote up a simple micro-benchmark >>> that repeats this test with Integer lists of varying sizes. I ran it with >>> openjdk and did not see *any* performance difference. I have attached the >>> quick-and-dirty code and included the sample results at the end. >>> >>> Amit >>> >>> ============================================= >>> Here are sample results: java -cp . -Xmx1500M com.test.Test >>> >>> iteration with 1000 elements >>> long way: 1, short way: 1 >>> long way: 1, short way: 1 >>> long way: 2, short way: 3 >>> long way: 1, short way: 3 >>> long way: 2, short way: 5 >>> long way: 9, short way: 7 >>> long way: 1, short way: 2 >>> long way: 10, short way: 2 >>> long way: 0, short way: 2 >>> long way: 0, short way: 1 >>> >>> >>> iteration with 1000000 elements >>> long way: 11, short way: 12 >>> long way: 14, short way: 11 >>> long way: 20, short way: 20 >>> long way: 20, short way: 22 >>> long way: 27, short way: 27 >>> long way: 28, short way: 30 >>> long way: 38, short way: 42 >>> long way: 37, short way: 42 >>> long way: 45, short way: 45 >>> long way: 46, short way: 49 >>> >>> >>> iteration with 10000000 elements >>> long way: 124, short way: 124 >>> long way: 125, short way: 125 >>> long way: 280, short way: 262 >>> long way: 282, short way: 262 >>> long way: 349, short way: 345 >>> long way: 348, short way: 344 >>> long way: 529, short way: 499 >>> long way: 566, short way: 663 >>> long way: 530, short way: 508 >>> long way: 530, short way: 508 >>> >>> >>> >>> On Thu, Jun 4, 2009 at 1:58 PM, Aaron Steele <[email protected]> wrote: >>>> >>>> Do'h! Yeah, using the name 'ints' probably wasn't a good choice here. >>>> Looks like I should re-read Item 56: Adhere to generally accepted >>>> naming conventions. :) >>>> >>>> On Thu, Jun 4, 2009 at 1:09 PM, Alex Rudnick <[email protected]> wrote: >>>> > >>>> > Yeesh, pardon. That's an ArrayList called "ints" of Integers, not >>>> > containing ints. I retract that statement! >>>> > >>>> > On Thu, Jun 4, 2009 at 4:04 PM, Alex Rudnick <[email protected]> wrote: >>>> >> Sounds like boxing/unboxing overhead, in that case! >>>> >> >>>> >> What if you tried that with an array of native ints? >>>> >> >>>> >> On Thu, Jun 4, 2009 at 3:47 PM, Aaron Steele <[email protected]> >>>> >> wrote: >>>> >>> >>>> >>> So item 46 in Effective Java says that there shouldn't be a >>>> >>> performance penalty using the nice for loops. But the following test >>>> >>> in Eclipse on my machine (MacBook Pro, Intel Core Duo, 2.16 GHz) shows >>>> >>> a performance penalty. >>>> >>> >>>> >>> Given an ArrayList called ints with 1 million Integers, this takes 31 >>>> >>> milliseconds: >>>> >>> for (int i = 0, size = ints.size(); i < size; i++) >>>> >>> ints.get(i).intValue(); >>>> >>> >>>> >>> And this takes 76 milliseconds: >>>> >>> for (Integer i : ints) >>>> >>> i.intValue(); >>>> >>> >>>> >>> What am I missing? Probably just some super naive testing on my part. >>>> >>> :) >>>> > >>>> > -- >>>> > Alex Rudnick >>>> > swe, gwt, atl >>>> > >>>> > > >>>> > >>>> >>>> >>>> >>>> -- >>>> >>>> Sent from Piedmont, CA, United States >>>> >>>> >>> >>> >>> >>> >>> >> > --~--~---------~--~----~------------~-------~--~----~ http://groups.google.com/group/Google-Web-Toolkit-Contributors -~----------~----~----~----~------~----~------~--~---
