Ada*_*sen 2 java benchmarking if-statement conditional-operator microbenchmark
我有这个想法,我会使用条件运算符将我的一些if块转换为单行.但是,我想知道是否存在速度差异.我运行了以下测试:
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");
}
Run Code Online (Sandbox Code Playgroud)
这是我的结果:
类型1使用了这么长:3293937157 ns
类型2占用了这么长:2856769127 ns
我在这里做错了吗?
假设s.equals("")必然如此,这是一种使代码更快的可行方法吗?
, is this a viable way to make your code faster?
Run Code Online (Sandbox Code Playgroud)
如果您String s;是非静态字段,甚至可以加快速度.当你是referencing十亿次时,静态场比非静态场要慢
public static void main(String[] args) {
startTime = System.nanoTime();
String s = "";
.
.
}
Run Code Online (Sandbox Code Playgroud)
编辑:
为什么它更快?
这是由于字符串引用到静态字段.
你可以在它的字节码中看到它
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
Run Code Online (Sandbox Code Playgroud)
如你所见getStatic,putStatic将被称为十亿次,它的作用是它将调用静态字段的引用并使用putStatic放置字符串的引用
getStatic - 获取类的静态字段值,其中字段由常量池索引中的字段引用标识(index1 << 8 + index2)
putStatic - 将静态字段设置为类中的值,其中字段由常量池中的字段引用索引标识(indexbyte1 << 8 + indexbyte2)
看看那些导致程序运行缓慢的位移
此外,如果你使用global/member field它将创建相同的字节码,但它将使用
getfield,putfield它与静态getStatic和putStatic
现在让我们看看non static field字节码
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
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,它只使用astore_1和aload_1保存并加载非静态字段的引用而无需额外的操作.
这听起来像是对我的过早优化.如果您仍打算以这种方式对这两种实现isEmpty()进行微基准测试,我建议使用,因为与之相比,底层代码更直接equals().通过这种方式,我的意思是编译器/ JVM将为您做的任何优化都不太可能由正在发生的事情触发equals(),并且更能反映一个实现相对于另一个实现的任何微小优势,假设真的很重要.
可读性应该是您决定是否要使用if-else或更好的规则? :.