jdk 1.5 performance

topic posted Wed, August 18, 2004 - 10:54 PM by  offlineMike
Share/Save/Bookmark
Advertisement
We just upgraded our app from running on jdk 1.4.2 to jdk 1.5 beta, and the app is *much* zippier. And the java process is doing the same amount of work using about 25% less memory.

One question... Is there a performance advantage in replacing code that looks like this...

for (Iterator iterator = collection.iterator(); iterator.hasNext(); ) {
MyObject obj = (MyObject) iter.next();
}

with code that uses the new generic iterator syntax?
posted by:
Mike
SF Bay Area
Advertisement
Advertisement
  • Re: jdk 1.5 performance

    Thu, August 19, 2004 - 10:38 PM
    Since no one responded, I decided to spend a little time experimenting with generics to see if the new generic looping syntax is faster than the old Iterator-and-cast loop syntax. If my experiment is valid, the answer is no.

    The output of 3 test runs of the following code is this:
    Old way: 5450
    New way: 5223
    Old way: 5341
    New way: 5354
    Old way: 5546
    New way: 5367


    cat test.java

    import java.util.*;

    public class test {

    public static long oldWay(int numElements, int numRepetitions) {
    List list = new ArrayList();
    for (int i = 0; i < numElements; i++) {
    list.add(new Integer(i));
    }

    int i = 0;
    int j = 0;
    long t1 = System.currentTimeMillis();
    for (int rep = 0; rep < numRepetitions; rep++) {
    for (Iterator iter = list.iterator(); iter.hasNext(); ) {
    i = ((Integer) iter.next()).intValue();
    j += i;
    }
    }
    long t2 = System.currentTimeMillis();
    return t2-t1;
    }

    public static long newWay(int numElements, int numRepetitions) {
    List<Integer> list = new ArrayList<Integer>();
    for (int i = 0; i < numElements; i++) {
    list.add(new Integer(i));
    }

    int j = 0;
    long t1 = System.currentTimeMillis();
    for (int rep = 0; rep < numRepetitions; rep++) {
    for (Integer i : list) {
    j += i;
    }
    }
    long t2 = System.currentTimeMillis();
    return t2-t1;
    }

    public static void main(String[] args) {
    int numElements = 1000000;
    int numRepetitions = 100;
    System.out.println("Old way: "+oldWay(numElements, numRepetitions));
    System.out.println("New way: "+newWay(numElements, numRepetitions));
    }
    }
    • Ken
      Ken
      offline 2

      Re: jdk 1.5 performance

      Fri, August 20, 2004 - 5:13 AM
      The code looks good, but the number of samples is pretty small. But even at that, there's an average of 2.3% increase across this small sample size. Not horrible, but definitely a little better.

      Old New Difference
      5450 5223 4.17%
      5341 5354 -0.24%
      5546 5367 3.23%

      Average 2.38%

      You might want to list the machine type/speed it's on, and do a larger test set to get more accurate numbers though.

      If they can squeeze ANY improvement out of iteration after Java's been around almost a decade, is a minor miracle in and of itself.

      2% increase can equate to quite a bit of time if iteration loops are used extensively in a system, over the lifetime of the system itself.
      • Re: jdk 1.5 performance

        Fri, August 20, 2004 - 12:21 PM
        I'm using a 2.0 GHz AMD Opteron 246, running Linux 2.4.

        Interestingly -- if I increase numRepetitions by a factor of 10 and do 5 test runs, I get this output:

        With this output, the new way is (ever-so-slightly) slower than the old way.

        Old way: 59020, New way: 59697, -1.13%
        Old way: 59849, New way: 60020, -0.28%
        Old way: 60612, New way: 61898, -2.08%
        Old way: 59588, New way: 62587, -4.79%
        Old way: 77333, New way: 73256, +5.57%

        average change: -0.55%
        • Ken
          Ken
          offline 2

          Re: jdk 1.5 performance

          Fri, August 20, 2004 - 3:20 PM
          You know what they say, 'Lies, Damn Lies, and Statistics'

          How about dropping numRepetitions back to what it was and running the test 1000 times. It shouldn't be too hard to modify the code slightly to internally store/tally the results so you don't have to by hand.

          Also, try it the other way, torque up the numRepetitions by a factor of 100, then 1000 and see the results.

          Just curious.
        • Unsu...
           

          Re: jdk 1.5 performance

          Sun, August 22, 2004 - 9:39 AM
          I was discussing this subject with my new manager, and he claims that the actual compiled bytecodes for the old way and the new way should be nearly identical. The two main goals of using generics is to a) simplify the syntax for running iterations, and b) reduce the number of runtime cast exceptions. But the performance will likely be no different.

          The general problem with running simple tests like this one is that the newer JVM's have a way of skewing the results by optimizing the code while it's running.
          • Unsu...
             

            Re: jdk 1.5 performance

            Sun, August 22, 2004 - 11:20 AM
            There's an additional consideration to all of this, which is we don't know exactly what was happening with the rest of the computer while the test was being run. If another process required 100% cpu for a half second (an extreme example, but you get my drift) it could account for the changes in results.

            Could changes in GC in 1.5 account for this as well? Adding to a list constantly would change memory allocation for this list... right?
            • Ken
              Ken
              offline 2

              Re: jdk 1.5 performance

              Sun, August 22, 2004 - 1:05 PM
              That's why the sample size needs to be pretty large to accomodate this. By accumulating results internally and setting the number of iterations to some rediculously large amount, it should even out the ones where the CPU is being monopolized by another thread/process.
              • Re: jdk 1.5 performance

                Tue, August 31, 2004 - 10:16 PM
                When I started this thread, I was speculating that thee would be a performance benefit if the jdk's internal implementation of generic iteration eliminated the need to cast each of the loop values to the target type. My test program -- imperfect as it was -- was good enough to convince me that there is no huge performance win here. The following (which is excerpted from www.artima.com/intv/generics2.html) explains why...

                --------

                Quoting Anders Hejlsberg:

                Java's ... generics proposal had as a key design goal that it could run on an unmodified VM [Virtual Machine]. It is, of course, great that you don't have to modify your VM, but it also brings about a whole bunch of odd limitations. The limitations are not necessarily directly apparent, but you very quickly go, "Hmm, that's strange."

                For example, with Java generics, you don't actually get any of the execution efficiency that I talked about, because when you compile a generic class in Java, the compiler takes away the type parameter and substitutes Object everywhere. So the compiled image for List<T> is like a List where you use the type Object everywhere. Of course, if you now try to make a List<int>, you get boxing of all the ints. So there's a bunch of overhead there. Furthermore, to keep the VM happy, the compiler actually has to insert all of the type casts you didn't write. If it's a List of Object and you're trying to treat those Objects as Customers, at some point the Objects must be cast to Customers to keep the verifier happy. And really all they're doing in their implementation is automatically inserting those type casts for you. So you get the syntactic sugar, or some of it at least, but you don't get any of the execution efficiency. So that's issue number one I have with Java's solution.

                Issue number two, and I think this is probably an even bigger issue, is that because Java's generics implementation relies on erasure of the type parameter, when you get to runtime, you don't actually have a faithful representation of what you had at compile time. When you apply reflection to a generic List in Java, you can't tell what the List is a List of. It's just a List. Because you've lost the type information, any type of dynamic code-generation scenario, or reflection-based scenario, simply doesn't work. If there's one trend that's pretty clear to me, it's that there's more and more of that. And it just doesn't work, because you've lost the type information.
  • Re: jdk 1.5 performance

    Thu, September 30, 2004 - 11:10 AM
    This is called a micro-benchmark. I really doubt that you would see a significant difference on anything less than very large sets unless Sun made a coding error in the generics.

    It takes an expert to build a micro-benchmark and interpret it because there are so many other factors that can figure in. There is a really good discussion of how to do this on the Google 'Straight Talking Java' group. It includes code from Kirk Pepperdine of www.javaperformancetuning.com.
    • Re: jdk 1.5 performance

      Fri, October 1, 2004 - 9:06 AM
      he iterated through sets of 1,000,000 items 100 times...what does "large set" mean in this context? do you mean a larger data set, or a larger sample set (more tests)?
      • Re: jdk 1.5 performance

        Thu, October 7, 2004 - 12:59 PM
        A 1M x 100 seems large (I think >= 1000 would be a minimum test as any statistic less than 1000 the error cannot be calculated with confidence) but it does not look to me as if the deviation calculations, etc were done. Is it large enough as I said really takes an expert at micro-benchmarks to determine.

        So many things can affect such a test. Was the -server set? Are there other things in the algorithm that could have changed implementation wise that could affect the timings. Are the timings accurate? Is object creation between JDK's affecting it. Does the difference in GC affect it?

        I'm definitely not an expert and am just pointing out some of the difficulties of writing an accurate micro-benchmark test.

Recent topics in "Java Monkeys"

Topic Author Replies Last Post
Javascripting costs Schirin 3 May 17, 2007
Design patterns and principles emblylan 6 February 14, 2007
open source hosting alternatives? Mark 2 February 3, 2007
Ruby > Java Unsubscribed 6 January 9, 2007