Меня не очень порадовало отсутствие тестов, поэтому вот некоторые тесты, выполненные с использованием https://github.com/sirthias/scala-benchmarking-template,, который использует Google Caliper в фоновом режиме.Диаграммы содержат рассчитанные (ns / внутри цикла выполнения), но текстовые результаты прямо из консоли.Код:
package org.example
import annotation.tailrec
import com.google.caliper.Param
class Benchmark extends SimpleScalaBenchmark {
@Param(Array("10", "100", "1000", "10000"))
val length: Int = 0
var array: Array[Int] = _
override def setUp() {
array = new Array(length)
}
def timeRegular(reps: Int) = repeat(reps) {
var result = 0
array.foreach {value => {
val tuple = (value, value)
val (out1, out2) = tuple
result += out1
result += out2
}}
result
}
def timeUnpack(reps: Int) = repeat(reps) {
var result = 0
array.foreach {value =>{
val tuple = (value, value)
val out1 = tuple._1
val out2 = tuple._2
result += out1
result += out2
}}
result
}
def timeBoxedUnpack(reps: Int) = repeat(reps) {
var result = 0
array.foreach {value =>{
val tuple = (value, value, value)
val out1 = tuple._1
val out2 = tuple._2
val out3 = tuple._3
result += out1
result += out2
result += out3
}}
result
}
}
Scala 2.9.2
0% Scenario{vm=java, trial=0, benchmark=Regular, length=10} 102.09 ns; σ=1.04 ns @ 10 trials
8% Scenario{vm=java, trial=0, benchmark=Unpack, length=10} 28.23 ns; σ=0.27 ns @ 6 trials
17% Scenario{vm=java, trial=0, benchmark=BoxedUnpack, length=10} 110.17 ns; σ=1.95 ns @ 10 trials
25% Scenario{vm=java, trial=0, benchmark=Regular, length=100} 909.73 ns; σ=6.42 ns @ 3 trials
33% Scenario{vm=java, trial=0, benchmark=Unpack, length=100} 271.40 ns; σ=1.35 ns @ 3 trials
42% Scenario{vm=java, trial=0, benchmark=BoxedUnpack, length=100} 946.59 ns; σ=8.38 ns @ 3 trials
50% Scenario{vm=java, trial=0, benchmark=Regular, length=1000} 8966.33 ns; σ=40.17 ns @ 3 trials
58% Scenario{vm=java, trial=0, benchmark=Unpack, length=1000} 2517.54 ns; σ=4.56 ns @ 3 trials
67% Scenario{vm=java, trial=0, benchmark=BoxedUnpack, length=1000} 9374.71 ns; σ=68.25 ns @ 3 trials
75% Scenario{vm=java, trial=0, benchmark=Regular, length=10000} 81244.84 ns; σ=661.81 ns @ 3 trials
83% Scenario{vm=java, trial=0, benchmark=Unpack, length=10000} 23502.73 ns; σ=122.83 ns @ 3 trials
92% Scenario{vm=java, trial=0, benchmark=BoxedUnpack, length=10000} 112683.27 ns; σ=1101.51 ns @ 4 trials
length benchmark ns linear runtime
10 Regular 102.1 =
10 Unpack 28.2 =
10 BoxedUnpack 110.2 =
100 Regular 909.7 =
100 Unpack 271.4 =
100 BoxedUnpack 946.6 =
1000 Regular 8966.3 ==
1000 Unpack 2517.5 =
1000 BoxedUnpack 9374.7 ==
10000 Regular 81244.8 =====================
10000 Unpack 23502.7 ======
10000 BoxedUnpack 112683.3 ==============================
![Chart showing the above data](https://i.stack.imgur.com/97iLh.png)
Scala 2.10.3
0% Scenario{vm=java, trial=0, benchmark=Regular, length=10} 28.26 ns; σ=0.13 ns @ 3 trials
8% Scenario{vm=java, trial=0, benchmark=Unpack, length=10} 28.27 ns; σ=0.07 ns @ 3 trials
17% Scenario{vm=java, trial=0, benchmark=BoxedUnpack, length=10} 109.56 ns; σ=2.27 ns @ 10 trials
25% Scenario{vm=java, trial=0, benchmark=Regular, length=100} 273.40 ns; σ=2.73 ns @ 5 trials
33% Scenario{vm=java, trial=0, benchmark=Unpack, length=100} 271.25 ns; σ=2.63 ns @ 6 trials
42% Scenario{vm=java, trial=0, benchmark=BoxedUnpack, length=100} 1088.00 ns; σ=10.60 ns @ 3 trials
50% Scenario{vm=java, trial=0, benchmark=Regular, length=1000} 2516.30 ns; σ=7.13 ns @ 3 trials
58% Scenario{vm=java, trial=0, benchmark=Unpack, length=1000} 2525.00 ns; σ=24.25 ns @ 6 trials
67% Scenario{vm=java, trial=0, benchmark=BoxedUnpack, length=1000} 10188.98 ns; σ=101.32 ns @ 3 trials
75% Scenario{vm=java, trial=0, benchmark=Regular, length=10000} 25886.80 ns; σ=116.33 ns @ 3 trials
83% Scenario{vm=java, trial=0, benchmark=Unpack, length=10000} 25938.97 ns; σ=76.02 ns @ 3 trials
92% Scenario{vm=java, trial=0, benchmark=BoxedUnpack, length=10000} 115629.82 ns; σ=1159.41 ns @ 5 trials
length benchmark ns linear runtime
10 Regular 28.3 =
10 Unpack 28.3 =
10 BoxedUnpack 109.6 =
100 Regular 273.4 =
100 Unpack 271.2 =
100 BoxedUnpack 1088.0 =
1000 Regular 2516.3 =
1000 Unpack 2525.0 =
1000 BoxedUnpack 10189.0 ==
10000 Regular 25886.8 ======
10000 Unpack 25939.0 ======
10000 BoxedUnpack 115629.8 ==============================
![Chart showing the above data](https://i.stack.imgur.com/GpMh1.png)
Заключение
Распаковка кортежей происходит быстро, пока арность кортежа <= 2. Если оно больше 2, слишком много косвенных ссылок и для компилятора Hotspot для оптимизации.</p>
В Scala 2.9.2 есть какие-то странные проблемы, делающие назначение с кортежами быстрее, чем обычное назначение.Странно, но это, вероятно, можно игнорировать.
Это делается с помощью
java version "1.7.0_45"
Java(TM) SE Runtime Environment (build 1.7.0_45-b18)
Java HotSpot(TM) 64-Bit Server VM (build 24.45-b08, mixed mode)