我正在开发一个用 Kotlin 编写的游戏,并且正在研究如何改善 GC 流失率。流失的主要来源之一是在主游戏/渲染循环中调用的 for 循环,导致分配迭代器。
翻到文档,我找到了这一段:
A for loop over an array is compiled to an index-based loop that does not create an iterator object.
If you want to iterate through an array or a list with an index, you can do it this way:
for (i in array.indices)
print(array[i])
Note that this “iteration through a range” is compiled down to optimal implementation with no extra objects created.
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-loop。然而,我得到的是这样的:
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(coll.indices 中的 i)
范围分配for (i in 0..coll.size)
: 没有分配for (el in coll)
:迭代器分配coll.forEach
:迭代器分配最佳答案
要在不分配额外对象的情况下迭代数组,您可以使用以下方法之一。
for
-循环 for (e in arr) {
println(e)
}
forEach
扩展 arr.forEach {
println(it)
}
forEachIndexed
扩展,如果你需要知道每个元素的索引 arr.forEachIndexed { index, e ->
println("$e at $index")
}
https://stackoverflow.com/questions/37609071/