我一直在阅读3 / E的有效Java。
在阅读有关哈希码的部分时,(第51页)我注意到书中说
31的一个不错的特性是乘法可以用移位和减法代替,以在某些体系结构上获得更好的性能:
31 * i == (i << 5) - i
。现代VM自动执行这种优化。
我认为这很有意义。我想知道这种优化发生时代码将变得更快。因此,我编写了一个简短的代码来查看此类优化的影响。
但是,似乎没有明显的差异。因此,我编写了更简单的代码,以检查是否进行了这种优化。
以下是我的示例代码。
fun main() {
val num = Random.nextInt()
val a = num * 30
val b = num * 31
val c = num * 32
println("$a, $b, $c")
}
这是从IntelliJ的Kotlin字节码功能获得的编译后的机器代码。
L1
LINENUMBER 5 L1
ILOAD 0
BIPUSH 30
IMUL
ISTORE 1
L2
LINENUMBER 6 L2
ILOAD 0
BIPUSH 31
IMUL
ISTORE 2
L3
LINENUMBER 7 L3
ILOAD 0
BIPUSH 32
IMUL
ISTORE 3
显然,没有区别。我们按每个号码,然后致电IMUL
。我认为优化可能是在将Java字节码编译成实际的机器代码时进行的,但是我从未检查过这一方面,所以我不知道如何确认我的理论。我搜索了一下,似乎我要寻找的关键字是JIT编译器,它似乎将.class转换为特定于CPU的机器代码。
我以为,也许我可以尝试通过JIT编译器将此代码转换为特定于CPU的机器代码,但是那意味着我在一个特定的CPU(而非所有CPU)上检查了这一理论。我想看看它是否“通常是真的”,但这将花费太多时间。
因此,是否有任何方法可以确认上述代码实际上(通常)由编译器进行了优化?如果将来我有类似的问题,应该去哪里找?我的意思是,当我对Java行为感到好奇时,我去了oracle并检查JVM参考或Java se参考。但是,编译器行为如何?我应该从哪里开始?
这是一个很长的问题。感谢您花费宝贵的时间阅读此问题。
(只是一个补充说明)
我在https://godbolt.org/上检查了C和python ,并确认对于C,它实际上已经优化。
int test(int num) {
int n = rand();
int a= n*30;
int b= n*31;
int c= n*32;
return a * b * c;
}
test:
push rbp
mov rbp, rsp
sub rsp, 32
mov DWORD PTR [rbp-20], edi
call rand
mov DWORD PTR [rbp-4], eax
mov eax, DWORD PTR [rbp-4]
imul eax, eax, 30
mov DWORD PTR [rbp-8], eax
mov edx, DWORD PTR [rbp-4]
mov eax, edx
sal eax, 5
sub eax, edx
mov DWORD PTR [rbp-12], eax
mov eax, DWORD PTR [rbp-4]
sal eax, 5
mov DWORD PTR [rbp-16], eax
mov eax, DWORD PTR [rbp-8]
imul eax, DWORD PTR [rbp-12]
imul eax, DWORD PTR [rbp-16]
leave
ret
但是,python不是。
num = randint()
a = num * 30
b = num * 31
c = num * 32
5 18 LOAD_NAME 2 (num)
20 LOAD_CONST 2 (30)
22 BINARY_MULTIPLY
24 STORE_NAME 3 (a)
6 26 LOAD_NAME 2 (num)
28 LOAD_CONST 3 (31)
30 BINARY_MULTIPLY
32 STORE_NAME 4 (b)
7 34 LOAD_NAME 2 (num)
36 LOAD_CONST 4 (32)
38 BINARY_MULTIPLY
40 STORE_NAME 5 (c)
42 LOAD_CONST 5 (None)
44 RETURN_VALUE
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句