gpt4 book ai didi

java - 具有 const 参数的不可变对象(immutable对象)是否会被优化为仅由 Kotlin 编译器实例化一次

转载 作者:行者123 更新时间:2023-12-04 19:25:17 25 4
gpt4 key购买 nike

Java 中有许多不可变的类,如 String和原始包装类,Kotlin 引入了许多其他类,如 Range子类和不可变 Collection子类。

用于迭代 Range s,来自 Control Flow: if, when, for, while - Kotlin Programming Language我们已经知道:

A for loop over a range or an array is compiled to an index-based loop that does not create an iterator object.



但是在处理 Range 的其他情况下s 这种优化是不可能的。

当使用 const 参数创建此类不可变类时,或者更一般地说,使用 const 参数递归创建类时,只实例化一次类将带来性能提升。 (换句话说,如果我们称其为 const 不可变实例化,则当且仅当它的所有参数都是常量或 const 不可变实例化时,实例化才是 const 不可变实例化。)因为 Java 编译器没有一种机制来知道是否一个类是不可变的,Kotlin 编译器是否根据其已知的不可变类的知识将此类类优化为仅实例化一次?

对于更具体的应用示例,请考虑以下代码:
repeat(1024) {
doSomething(('a'..'z').random())
}
val LOWERCASE_ALPHABETS = 'a'..'z'
repeat(1024) {
doSomething(LOWERCASE_ALPHABETS.random())
}

第二个会带来任何性能改进吗?

最佳答案

我认为您能做的最好的事情是检查编译器生成的指令。

我们来看下面的源代码:

fun insideRepeat() {
repeat(1024) {
doSomething(('a'..'z').random())
}
}

fun outsideRepeat() {
val range = 'a'..'z'
repeat(1024) {
doSomething(range.random())
}
}

对于 insideRepeat它会产生类似的东西(我添加了一些评论):
    public final static insideRepeat()V
L0
LINENUMBER 2 L0
SIPUSH 1024
ISTORE 0
L1
L2
ICONST_0
ISTORE 1
ILOAD 0
ISTORE 2
L3
ILOAD 1
ILOAD 2
IF_ICMPGE L4 // loop termination condition
L5
ILOAD 1
ISTORE 3
L6
ICONST_0
ISTORE 4
L7 // loop body
LINENUMBER 3 L7
BIPUSH 97
ISTORE 5
NEW kotlin/ranges/CharRange
DUP
ILOAD 5
BIPUSH 122
INVOKESPECIAL kotlin/ranges/CharRange.<init> (CC)V // new instance created inside the loop
INVOKESTATIC FooKt.random (Lkotlin/ranges/CharRange;)Ljava/lang/Object;
INVOKESTATIC FooKt.doSomething (Ljava/lang/Object;)Ljava/lang/Object;
POP

而对于 outsideRepeat它将生成:
public final static outsideRepeat()V
L0
LINENUMBER 8 L0
BIPUSH 97
ISTORE 1
NEW kotlin/ranges/CharRange
DUP
ILOAD 1
BIPUSH 122
INVOKESPECIAL kotlin/ranges/CharRange.<init> (CC)V // range created outside loop
ASTORE 0
L1
LINENUMBER 9 L1
SIPUSH 1024
ISTORE 1
L2
L3
ICONST_0
ISTORE 2
ILOAD 1
ISTORE 3
L4
ILOAD 2
ILOAD 3
IF_ICMPGE L5 // termination condition
L6
ILOAD 2
ISTORE 4
L7
ICONST_0
ISTORE 5
L8
LINENUMBER 10 L8
ALOAD 0
INVOKESTATIC FooKt.random (Lkotlin/ranges/CharRange;)Ljava/lang/Object;
INVOKESTATIC FooKt.doSomething (Ljava/lang/Object;)Ljava/lang/Object;
POP

所以看起来第二个版本确实带来了性能改进(还考虑到 GC 将需要释放更少的对象)

关于java - 具有 const 参数的不可变对象(immutable对象)是否会被优化为仅由 Kotlin 编译器实例化一次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59103493/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com