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?
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?
Advertisement
Advertisement
-
Re: jdk 1.5 performance
Thu, August 19, 2004 - 10:38 PMSince 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));
}
}
-
-
Re: jdk 1.5 performance
Fri, August 20, 2004 - 5:13 AMThe 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 PMI'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%
-
-
Re: jdk 1.5 performance
Fri, August 20, 2004 - 3:20 PMYou 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 AMI 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 AMThere'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? -
-
Re: jdk 1.5 performance
Sun, August 22, 2004 - 1:05 PMThat'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 PMWhen 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 AMThis 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 AMhe 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 PMA 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.
-
-
