Hi Ray,

Thanks for the feedback. Just for kicks, I updated the micro-benchmark to
add more sub-types of List and re-ran the test. I found that with jdk6 (both
openjdk6 and sun's jdk6) both versions still took the same time.However,
with sun's jdk5, I did find a 10+% improvement when rewriting for loops to
avoid iterators. I haven't dug into the JRE code to see what has changed,
but this might offer a quick fix to the performance problem.

Dan: can you see if switching to openjdk6 or sun's jdk6 fixes the
performance issue?

I have attached the updated benchmark. Am I missing something? Despite being
difficult, it will be nice to come up with a benchmark that demonstrates
this performance difference.

Amit


On Thu, Jun 4, 2009 at 8: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
-~----------~----~----~----~------~----~------~--~---

/*
 * Copyright 2008 Google Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.test;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.Stack;
import java.util.Vector;

/**
 * An implementation for Test.
 */
public class Test {
  static final int ITERATIONS = 5;

  public static void main(String args[]) {

    String listType = "arraylist";
    if (args.length > 0) {
      listType = args[0];
    }
    for (int maxSize : new int[] {1000, 1000 * 1000, 1000 * 1000 * 10}) {
      long start = 0, shortWay = 0, longWay = 0;
      System.out.println("\n\niteration with " + maxSize + " elements");
      for (int i = 0; i < ITERATIONS; i++) {
        List<Integer> integerList = constructList(maxSize, listType);
        start = System.currentTimeMillis();
        findMaxLongWay(integerList);
        longWay = System.currentTimeMillis() - start;
        findMaxShortWay(integerList);
        shortWay = System.currentTimeMillis() - start - longWay;
        System.out.println("long way: " + longWay + ", short way: " + shortWay);

        // repeat in reverse order to get rid of memory/caching effects
        start = System.currentTimeMillis();
        findMaxShortWay(integerList);
        shortWay = System.currentTimeMillis() - start;
        findMaxLongWay(integerList);
        longWay = System.currentTimeMillis() - start - shortWay;
        System.out.println("long way: " + longWay + ", short way: " + shortWay);
      }
    }
  }

  private static List<Integer> constructList(int maxSize, String listType) {
    Random r = new Random();
    // see if having multiple sub-types of List has any effect on hotspot
    List<Integer> integerList = null;
    if (listType.equals("LinkedList")) {
      integerList = new LinkedList<Integer>();
    } else if (listType.equals("Stack")) {
      integerList = new Stack<Integer>();
    } else if (listType.equals("Vector")) {
      integerList = new Vector<Integer>();
    } else { // the default
      integerList = new ArrayList<Integer>();
    }
   
    for (int i = 0; i < maxSize; i++) {
      integerList.add(r.nextInt());
    }
    return integerList;
  }

  private static int findMaxLongWay(List<Integer> integerList) {
    int max = -1;
    for (int i = 0, size = integerList.size(); i < size; i++) {
      int value = integerList.get(i).intValue();
      if (max < value) {
        max = value;
      }
    }
    return max;
  }

  private static int findMaxShortWay(List<Integer> integerList) {
    int max = -1;
    for (Integer i : integerList) {
      int value = i.intValue();
      if (max < value) {
        max = value;
      }
    }
    return max;
  }

}

Reply via email to