Индексирование по массивам в цикле while в Scala происходит так же быстро, как и в Java. (Цикл for в Scala не является низкоуровневой конструкцией Java, поэтому она не будет работать так, как вы хотите.)
Таким образом, если в Java вы видите
for (int i=0 ; i < array.length ; i++) sum += array(i)
в Scala вы должны написать
var i=0
while (i < array.length) {
sum += array(i)
i += 1
}
и если вы сделаете свои тесты соответствующим образом, вы не найдете никакой разницы в скорости.
Если у вас есть итераторы, Scala в большинстве случаев работает так же быстро, как и Java. Например, если у вас есть ArrayList двойных значений, а в Java вы добавляете их, используя
for (double d : arraylist) { sum += d }
тогда в Scala вы будете примерно так же быстро - если использовать эквивалентную структуру данных, такую как ArrayBuffer - с
arraybuffer.foreach( sum += _ )
и не слишком далеко от отметки с любым из
sum = (0 /: arraybuffer)(_ + _)
sum = arraybuffer.sum // 2.8 only
Имейте в виду, однако, что есть штраф за смешивание высокоуровневых и низкоуровневых конструкций. Например, если вы решили начать с массива, но затем использовать «foreach» для него вместо индексации, Scala должен обернуть его в коллекцию (ArrayOps
в 2.8), чтобы заставить его работать, и часто будет иметь также упаковывать примитивы.
В любом случае, для тестирования производительности эти две функции являются вашими друзьями:
def time[F](f: => F) = {
val t0 = System.nanoTime
val ans = f
printf("Elapsed: %.3f\n",1e-9*(System.nanoTime-t0))
ans
}
def lots[F](n: Int, f: => F): F = if (n <= 1) f else { f; lots(n-1,f) }
Например:
val a = Array.tabulate(1000000)(_.toDouble)
val ab = new collection.mutable.ArrayBuffer[Double] ++ a
def adSum(ad: Array[Double]) = {
var sum = 0.0
var i = 0
while (i<ad.length) { sum += ad(i); i += 1 }
sum
}
// Mixed array + high-level; convenient, not so fast
scala> lots(3, time( lots(100,(0.0 /: a)(_ + _)) ) )
Elapsed: 2.434
Elapsed: 2.085
Elapsed: 2.081
res4: Double = 4.999995E11
// High-level container and operations, somewhat better
scala> lots(3, time( lots(100,(0.0 /: ab)(_ + _)) ) )
Elapsed: 1.694
Elapsed: 1.679
Elapsed: 1.635
res5: Double = 4.999995E11
// High-level collection with simpler operation
scala> lots(3, time( lots(100,{var s=0.0;ab.foreach(s += _);s}) ) )
Elapsed: 1.171
Elapsed: 1.166
Elapsed: 1.162
res7: Double = 4.999995E11
// All low level operations with primitives, no boxing, fast!
scala> lots(3, time( lots(100,adSum(a)) ) )
Elapsed: 0.185
Elapsed: 0.183
Elapsed: 0.186
res6: Double = 4.999995E11