【发布时间】:2016-06-03 08:01:45
【问题描述】:
我正在开发一个用 Kotlin 编写的游戏,并且正在研究如何改善 GC 流失率。流失的主要来源之一是在主游戏/渲染循环中调用的 for 循环,导致分配迭代器。
翻到文档,我找到了这一段:
数组上的 for 循环被编译为基于索引的循环,不会创建迭代器对象。
如果你想遍历一个带有索引的数组或列表,你可以这样做:
for (i in array.indices)
print(array[i])
请注意,这种“遍历范围”会被编译为最佳实现,而不会创建额外的对象。
https://kotlinlang.org/docs/reference/control-flow.html#for-loops
这是真的吗?为了验证,我使用了这个简单的 Kotlin 程序并检查了生成的字节码:
fun main(args: Array<String>) {
val arr = arrayOf(1, 2, 3)
for (i in arr.indices) {
println(arr[i])
}
}
根据上面的引用,这不应该导致任何对象被分配,而是被编译成一个很好的旧 Java-5 前风格的 for 循环。然而,我得到的是这样的:
41: aload_1
42: checkcast #23 // class "[Ljava/lang/Object;"
45: invokestatic #31 // Method kotlin/collections/ArraysKt.getIndices:([Ljava/lang/Object;)Lkotlin/ranges/IntRange;
48: dup
49: invokevirtual #37 // Method kotlin/ranges/IntRange.getFirst:()I
52: istore_2
53: invokevirtual #40 // Method kotlin/ranges/IntRange.getLast:()I
56: istore_3
57: iload_2
58: iload_3
59: if_icmpgt 93
在我看来,这就像调用了一个名为 getIndices 的方法,它分配了一个临时的 IntRange 对象来备份此循环中的边界检查。这是一个“没有创建额外对象”的“最佳实现”,还是我遗漏了什么?
更新: 因此,在多玩了一会儿并查看了答案之后,以下内容似乎适用于 Kotlin 1.0.2:
数组:
-
for (i in array.indices):范围分配 -
for (i in 0..array.size):没有分配 -
for (el in array):没有分配 -
array.forEach:没有分配
收藏:
-
for (i in coll.indices)范围分配 -
for (i in 0..coll.size):没有分配 -
for (el in coll): 迭代器分配 -
coll.forEach: 迭代器分配
【问题讨论】:
-
KT-12611 声明
indices优化已包含在 Kotlin 1.0.3 中。
标签: kotlin