I am experiencing some quite strange performance behaviour when evaluating some very specific if conditions.
Basically I have found that I can construct two conditions a and b such that if(a)
is 10 times faster than if(a && b)
even if a
is always false, which seems to clash directly with the fact that Java should do lazy evaluation of conditions.
The case occurs when I have a
to be someDate.after(startdate)
and b
to be someDate.before(enddate)
- i.e a fairly standard range condition.
Below I've attached the code I use to show this particular issue. I've run the code on Windows 7 with Java 7, and one of my colleagues have run it on Windows 7 with java 6,7 and 8 - all with the same result.
Can anyone explain why this could happen?
import java.util.Date;
public class DateWeirdness {
public static void main(String[] args) {
Date start = new Date();
System.out.println("if(a) - a always false");
System.out.println(timeBasic(2000000000, start, start.getTime() - 4000000000L));
start = new Date();
System.out.println("if(a && b) - a always false, a and b both date method");
System.out.println(timeAdv(2000000000, start, start.getTime() - 4000000000L, new Date()));
start = new Date();
System.out.println("if(a && b) - a always false, b is condition on longs not date");
System.out.println(timeAdv2(2000000000, start, start.getTime() - 4000000000L, new Date().getTime()));
start = new Date();
System.out.println("if(a) - a always false - condition on long");
System.out.println(timeBasicL(2000000000, start.getTime(), start.getTime() - 4000000000L));
start = new Date();
System.out.println("if(a && b) - a always false, a and and b both conditions on long");
System.out.println(timeAdvL(2000000000, start.getTime(), start.getTime() - 4000000000L, new Date().getTime()));
start = new Date();
System.out.println("if(a && b) - a always false, b always true");
System.out.println(timeAdv(2000000000, start, start.getTime() - 4000000000L, new Date()));
start = new Date();
System.out.println("if(a && b) - both true");
System.out.println(timeAdv(2000000000, start, start.getTime() + 1, new Date(start.getTime() + 4000000000L)));
start = new Date();
System.out.println("if(a && b) - a always true, b always false");
System.out.println(timeAdv(2000000000, start, new Date(start.getTime() + 4000000001L).getTime(), new Date(start.getTime() + 4000000000L)));
}
private static int timeBasic(int size, Date start, long l) {
long begin = System.currentTimeMillis();
int c = 0;
for (int i = 0; i < size; i++) {
Date date = new Date(l++);
if (start.before(date)) {
c++;
}
}
System.out.println(System.currentTimeMillis() - begin);
return c;
}
private static int timeAdv(int size, Date start, long l, Date end) {
long begin = System.currentTimeMillis();
int c = 0;
for (int i = 0; i < size; i++) {
Date date = new Date(l++);
if (start.before(date) && end.after(date)) {
c++;
}
}
System.out.println(System.currentTimeMillis() - begin);
return c;
}
private static int timeAdv2(int size, Date start, long l, long end) {
long begin = System.currentTimeMillis();
int c = 0;
for (int i = 0; i < size; i++) {
Date date = new Date(l++);
if (start.before(date) && end > l) {
c++;
}
}
System.out.println(System.currentTimeMillis() - begin);
return c;
}
private static int timeBasicL(int size, long start, long l) {
long begin = System.currentTimeMillis();
int c = 0;
for (int i = 0; i < size; i++) {
l++;
if (start < l) {
c++;
}
}
System.out.println(System.currentTimeMillis() - begin);
return c;
}
private static int timeAdvL(int size, long start, long l, long end) {
long begin = System.currentTimeMillis();
int c = 0;
for (int i = 0; i < size; i++) {
l++;
if (start < l && end > l) {
c++;
}
}
System.out.println(System.currentTimeMillis() - begin);
return c;
}
}
When running it locally I get the following output. The interesting tests are the three first ones. 640
is the performance in milliseconds of doing if(a)
, 7079
is the performance of doing if(a && b)
, where a
and b
are as described above. 710
is the performance of doing if(a && b)
where b
is someDateAsLong < endDateAsLong
.
if(a) - a always false
640
0
if(a && b) - a always false, a and b both date method
7079
0
if(a && b) - a always false, b is condition on longs not date
710
0
if(a) - a always false - condition on long
639
0
if(a && b) - a always false, a and and b both conditions on long
708
0
if(a && b) - a always false, b always true
6873
0
if(a && b) - both true
11995
2000000000
if(a && b) - a always true, b always false
13746
0