问题
I had the idea I would turn some of my if blocks into single lines, using the conditional operator. However, I was wondering if there would be a speed discrepancy. I ran the following test:
static long startTime;
static long elapsedTime;
static String s;
public static void main(String[] args) {
startTime = System.nanoTime();
s = "";
for (int i= 0; i < 1000000000; i++) {
if (s.equals("")) {
s = "";
}
}
elapsedTime = System.nanoTime() - startTime;
System.out.println("Type 1 took this long: " + elapsedTime + " ns");
startTime = System.nanoTime();
s = "";
for (int i= 0; i < 1000000000; i++) {
s = (s.equals("") ? "" : s);
}
elapsedTime = System.nanoTime() - startTime;
System.out.println("Type 2 took this long: " + elapsedTime + " ns");
}
This is my result:
Type 1 took this long: 3293937157 ns
Type 2 took this long: 2856769127 ns
Am I doing something wrong here?
Assuming s.equals("")
necessarily is true, is this a viable way to make your code faster?
回答1:
The other answers have useful information that is relevant but none of them addresses the real question if the first form is more efficient than the second form.
This benchmarking does not provide reliable results since it's not done properly: one important "rule of thumb" in benchmarking Java code is to provide a warm-up. In this case, the first loop provides a warm-up to the second loop.
This answer provides additional instructions for micro-benchmarking as well as some useful links.
回答2:
, is this a viable way to make your code faster?
You can even make it faster if your String s;
is a non static field. Static-field is slower than non-static field when you are referencing
it a billion times
public static void main(String[] args) {
startTime = System.nanoTime();
String s = "";
.
.
}
EDIT:
Why is it faster??
It is due to the referencing of string to the static field.
You can see it in the byte code of it
0: ldc #23 // String
2: putstatic #25 // Field s:Ljava/lang/String;
5: iconst_0
6: istore_1
7: goto 22
10: getstatic #25 // Field s:Ljava/lang/String;
13: ldc #23 // String
15: invokevirtual #27 // Method java/lang/String.equals:(L
java/lang/Object;)Z
18: pop
19: iinc 1, 1
22: iload_1
23: ldc #33 // int 1000000000
25: if_icmplt 10
28: return
As you can see getStatic
and putStatic
will be called a billion times, what it does is that it will call the reference of the static field and put the reference of the string using putStatic
getStatic - get a static field value of a class, where the field is identified by field reference in the constant pool index (index1 << 8 + index2)
putStatic - set static field to value in a class, where the field is identified by a field reference index in constant pool (indexbyte1 << 8 + indexbyte2)
See those bit shifting that is the cause of the slowness of the program
Also if you are using a global/member field
it will create the same bytecode but instead it will use
getfield
and putfield
which is the same as static's getStatic
and putStatic
Now let see the non static field
bytecode
0: ldc #21 // String
2: astore_1
3: iconst_0
4: istore_2
5: goto 23
8: aload_1
9: ldc #21 // String
11: invokevirtual #23 // Method java/lang/String.equals:(L
java/lang/Object;)Z
14: ifeq 20
17: ldc #21 // String
19: astore_1
20: iinc 2, 1
23: iload_2
24: ldc #29 // int 1000000000
26: if_icmplt 8
29: return
As you can see it only uses astore_1
and aload_1
to save and load the reference of the non static field without extra operation.
回答3:
This does smell like premature optimization to me. If you still intend to microbenchmark both implementations this way, I suggest using isEmpty()
instead since the underlying code for that is more straightforward compared to equals()
. By that, I mean any optimization that the compiler/JVM will do for you will be less likely triggered by what's happening in equals()
, and more reflective of any minute benefits that one implementation has over the other, assuming that really matters.
Readability should be the better rule for you to decide whether you want to use if-else
or ? :
.
来源:https://stackoverflow.com/questions/25029785/speed-of-if-compared-to-conditional