kotlin - descargar - Matriz/lista de iteración sin asignaciones de objetos adicionales
kotlin vs scala (2)
Estoy trabajando en un juego escrito en Kotlin y estaba buscando mejorar la rotación de GC. Una de las principales fuentes de churn son los bucles for-for llamados en los bucles principales de juego / renderización que resultan en la asignación de iteradores.
Volviendo a la documentación, encontré este párrafo:
Un bucle for sobre una matriz se compila en un bucle basado en índices que no crea un objeto iterador.
Si desea recorrer una matriz o una lista con un índice, puede hacerlo de esta manera:
for (i in array.indices)
print(array[i])
Tenga en cuenta que esta "iteración a través de un rango" se compila para lograr una implementación óptima sin objetos adicionales creados.
https://kotlinlang.org/docs/reference/control-flow.html#for-loops
¿Es esto realmente cierto? Para verificar, tomé este sencillo programa de Kotlin e inspeccioné el código de byte generado:
fun main(args: Array<String>) {
val arr = arrayOf(1, 2, 3)
for (i in arr.indices) {
println(arr[i])
}
}
De acuerdo con la cita anterior, esto no debe dar como resultado ningún objeto asignado, sino que debe compilarse en un viejo estilo pre-Java-5 para el bucle. Sin embargo, lo que obtuve fue esto:
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
Esto me parece que se llama a un método llamado getIndices
que asigna un objeto IntRange
temporal para realizar una copia de seguridad de los límites en este bucle. ¿Cómo es esto una "implementación óptima" con "no se crean objetos adicionales", o me falta algo?
ACTUALIZACIÓN: Entonces, después de juguetear un poco más y mirar las respuestas, lo siguiente parece ser cierto para Kotlin 1.0.2:
Arrays:
-
for (i in array.indices)
: asignación de rango -
for (i in 0..array.size)
: sin asignación -
for (el in array)
: sin asignación -
array.forEach
: sin asignación
Colecciones:
-
for (i in coll.indices)
asignación de rango -
for (i in 0..coll.size)
: sin asignación -
for (el in coll)
: asignación de iteradores -
coll.forEach
: asignación de iteradores
Para iterar una matriz sin asignar objetos adicionales, puede utilizar una de las siguientes formas.
-
for
-loop
for (e in arr) {
println(e)
}
-
forEach
extensión
arr.forEach {
println(it)
}
-
forEachIndexed
extension, si necesita saber el índice de cada elemento
arr.forEachIndexed { index, e ->
println("$e at $index")
}
Por lo que sé, la única manera de definir un bucle for
asignación es
for (i in 0..count - 1)
Todas las demás formas conducen a una asignación de Range
o una asignación de Iterator
. Desafortunadamente, ni siquiera se puede definir un revés efectivo for
bucle.