我认为您能做的最好的事情是检查编译器生成的指令。
我们来看下面的源代码:
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 将需要释放更少的对象)