Code:
@annotation.tailrec
private def fastLoop(n: Int, a: Long = 0, b: Long = 1): Long =
if (n > 1) fastLoop(n - 1, b, a + b) else b
Bytecode:
private long fastLoop(int, long, long);
Code:
0: iload_1
1: iconst_1
2: if_icmple 21
5: iload_1
6: iconst_1
7: isub
8: lload 4
10: lload_2
11: lload 4
13: ladd
14: lstore 4
16: lstore_2
17: istore_1
18: goto 0
21: lload 4
23: lreturn
Ergebnis ist 53879289.462 ± 6289454.961 ops/s
:
https://travis-ci.org/plokhotnyuk/scala-vs-java/jobs/56117116#L2909
Java
Code:
private long fastLoop(int n, long a, long b) {
while (n > 1) {
long c = a + b;
a = b;
b = c;
n--;
}
return b;
}
Bytecode:
private long fastLoop(int, long, long);
Code:
0: iload_1
1: iconst_1
2: if_icmple 24
5: lload_2
6: lload 4
8: ladd
9: lstore 6
11: lload 4
13: lstore_2
14: lload 6
16: lstore 4
18: iinc 1, -1
21: goto 0
24: lload 4
26: lreturn
Ergebnis ist 17444340.812 ± 9508030.117 ops/s
:
https://travis-ci.org/plokhotnyuk/scala-vs-java/jobs/56117116#L2881
Ja, es hängt von der Umgebung param eters (JDK-Version, CPU-Modell & Frequenz des RAM) und dynamischen Zustand. Aber warum kann der gleiche Bytecode in der gleichen Umgebung eine stabile 2x-3x Differenz für einen Bereich von Funktionsargumenten erzeugen?
Hier ist eine Liste von ops/s Zahlen für verschiedene Werte von Funktionen Argumente von meinem Notebook mit Intel (R) Core (TM) i7-2640M CPU @ 2.80GHz (max 3.50GHz), RAM 12 GB DDR3-1333, Ubuntu 14.10, Oracle JDK 1.8.0_40-b25 64-Bit: "warum Werte von ops/s wie oben in nicht-linearer Weise abnehmen"
[info] Benchmark (n) Mode Cnt Score Error Units
[info] JavaFibonacci.loop 2 thrpt 5 171776163.027 ± 4620419.353 ops/s
[info] JavaFibonacci.loop 4 thrpt 5 144793748.362 ± 25506649.671 ops/s
[info] JavaFibonacci.loop 8 thrpt 5 67271848.598 ± 15133193.309 ops/s
[info] JavaFibonacci.loop 16 thrpt 5 54552795.336 ± 17398924.190 ops/s
[info] JavaFibonacci.loop 32 thrpt 5 41156886.101 ± 12905023.289 ops/s
[info] JavaFibonacci.loop 64 thrpt 5 24407771.671 ± 4614357.030 ops/s
[info] ScalaFibonacci.loop 2 thrpt 5 148926292.076 ± 23673126.125 ops/s
[info] ScalaFibonacci.loop 4 thrpt 5 139184195.527 ± 30616384.925 ops/s
[info] ScalaFibonacci.loop 8 thrpt 5 109050091.514 ± 23506756.224 ops/s
[info] ScalaFibonacci.loop 16 thrpt 5 81290743.288 ± 5214733.740 ops/s
[info] ScalaFibonacci.loop 32 thrpt 5 38937420.431 ± 8324732.107 ops/s
[info] ScalaFibonacci.loop 64 thrpt 5 22641295.988 ± 5961435.507 ops/s
Zusätzliche Frage
Sie müssten beginnen, indem Sie den Bytecode untersuchen. ISTR eine sehr ähnliche Frage, bei der der Unterschied implizite Schleife entrolling war. – chrylis
Können Sie den verwendeten Bechmarking-Mechanismus genauer beschreiben? Es scheint viel wahrscheinlicher, dass Ihre Messtechnik problematisch ist, als dass dies tatsächlich langsamer ist. –
Mein vorheriger Kommentar war nicht ganz klar. Was ich damit sagen will, ist, dass wenn ich diese benchmarkiere, ich das Ergebnis bekomme, dass die zwei Methoden genau gleich sind. Ich sehe keinen 3-fachen Unterschied. Ich sehe nicht einmal einen Unterschied von 10%. –