Reputation: 2459
While reading essential java item45, there are three different simple loops as shown in the code below with timing. The first and the third is preferred. But when I time them,
for N < 1,000,000:
length of the list: 1000000
sum is: 499999500000
fast method time: 25
sum is: 499999500000
slower method time: 5
sum is: 499999500000
range method time: 21
the second method is actually faster, I think this may because java compiler is smart enough to substitute the a.size() with the actual number.
However, when N grows, the second method indeed becomes slower. I am aware this experiment is naive and machine specific. I wonder if there is an explanation for the second method outperform the other two when N is small. (the program have been run multiple times)
length of the list: 10000000
sum is: 49999995000000
fast method time: 44
sum is: 49999995000000
slower method time: 48
sum is: 49999995000000
range method time: 37
The code:
public static void main(String [] args){
// test the speed of initialize 1 million elements
// timing two different loops.
// int N = 10000000;
int N = 1000000;
List<Integer> a = new ArrayList<Integer>();
for(int i = 0; i < N; ++i){
a.add(i);
}
System.out.println("length of the list: " + a.size());
long t1 = System.currentTimeMillis();
long sum = 0;
for(int i = 0, n = a.size(); i < n; ++i){
sum += a.get(i);
}
long t2 = System.currentTimeMillis();
System.out.println("sum is: " + sum);
System.out.println("fast method time: " + (t2 - t1));
t1 = System.currentTimeMillis();
sum = 0;
for(int i = 0; i < a.size(); ++i){
sum += a.get(i);
}
t2 = System.currentTimeMillis();
System.out.println("sum is: " + sum);
System.out.println("slower method time: " + (t2 - t1));
t1 = System.currentTimeMillis();
sum = 0;
for(int i: a){
sum += i;
}
t2 = System.currentTimeMillis();
System.out.println("sum is: " + sum);
System.out.println("range method time: " + (t2 - t1));
}
Upvotes: 2
Views: 125
Reputation: 23015
I was indeed having the same results than you:
length of the list: 1000000
sum is: 499999500000
fast method time: 32
sum is: 499999500000
slower method time: 12
sum is: 499999500000
range method time: 24
So I used javap -c
to dissasemble the bytecode, and I saw that javac
was not making any kind of optimization when seeing that N was small, and in deed, no optimization was being done.
So, I tried exchanging the order of the first two statements, and here is the result:
length of the list: 1000000
sum is: 499999500000
slower method time: 30
sum is: 499999500000
fast method time: 8
sum is: 499999500000
range method time: 25
So the difference between those two methods is not the method itself, but which one happens first will be the slower.
As for why it happens, it is still puzzling me (maybe deferred loading of some class? hot-code native compilation?)
Upvotes: 1