作者:Stupid锋_891 | 来源:互联网 | 2022-12-30 13:21
在字节代码级别,Java布尔值表示为0或1.我有一个表达式,结果为0或1,但它是使用int类型计算的.一个简单的例子是:
public static int isOdd_A(int value) {
return value & 1;
}
public static boolean isOdd_B(int value) {
return (value & 1) == 1;
}
上述方法的字节代码如下所示:
public static int isOdd_A(int);
descriptor: (I)I
Code:
0: iload_0
1: iconst_1
2: iand
3: ireturn
public static boolean isOdd_B(int);
descriptor: (I)Z
Code:
0: iload_0
1: iconst_1
2: iand
3: iconst_1
4: if_icmpne 11
7: iconst_1
8: goto 12
11: iconst_0
12: ireturn
返回布尔值的方法要大得多,并且包含一个分支,因此如果运行的机器代码是等效的,则它不是最佳的.
HotSpot JVM是否知道布尔版本可以优化为无网格机器代码?有没有办法欺骗Java使用基于int的字节代码来返回一个布尔值的方法(例如使用ASM)?
编辑:许多人认为这不值得担心,总的来说我同意.但是我确实创建了这个微基准测试并用jmh运行它,并注意到int版本大约10%的改进:
@Benchmark
public int countOddA() {
int odds = 0;
for (int n : numbers)
if (Test.isOdd_A(n) == 1)
odds++;
return odds;
}
@Benchmark
public int countOddB() {
int odds = 0;
for (int n : numbers)
if(Test.isOdd_B(n))
odds++;
return odds;
}
Benchmark Mode Cnt Score Error Units
OddBenchmark.countOddA thrpt 100 18393.818 ± 83.992 ops/s
OddBenchmark.countOddB thrpt 100 16689.038 ± 90.182 ops/s
我同意代码应该是可读的(这就是为什么我想要具有适当布尔接口的无分支int版本的性能),并且大多数时候这种优化级别是不合理的.然而,在这种情况下,即使所讨论的方法甚至不占大多数代码,也有10%的增益.
所以我们在这里可能会有一个案例,可以让HotSpot了解这种模式并生成更好的代码.