Array / List iteration без дополнительных распределений объектов

Я работаю над игрой, написанной в Котлине, и изучал улучшение оттока GC. Один из основных источников оттока – это петли, называемые в основных циклах игры / рендеринга, которые приводят к распределению итераторов.

Переходя к документации, я нашел этот пункт:

Цикл 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]) } } 

Согласно приведенной выше цитате, это не должно приводить к каким-либо выделенным объектам, но скомпилировать их до старого старого стиля pre-Java-5 для цикла. Однако я получил следующее:

  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 метод, называемый 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 : распределение итератора

Насколько я знаю, единственным способом определения цикла for является

 for (i in 0..count - 1) 

Все остальные формы приводят либо к распределению Range либо к распределению Iterator . К сожалению, вы даже не можете определить эффективную обратную for цикла.

Для итерации массива без выделения дополнительных объектов вы можете использовать один из следующих способов.

  1. for -loop
  for (e in arr) { println(e) } 
  1. forEach расширения
  arr.forEach { println(it) } 
  1. forEachIndexed , если вам нужно знать индекс каждого элемента
  arr.forEachIndexed { index, e -> println("$e at $index") }