まず結論
先日、「Java 8 Lambda 性能測定」にて、Lambdaを使用すると性能がまるで違うことを述べたのですが、間違いだったようです。
プログラムを改修して再試行したら、次の2つの速度性能はほぼ同じものになりました。
- 単純なfor文で総和を計算
- 1をLambda経由で呼び出す
改修後のプログラム
改修前は総和を計算しているものの、その結果をどこにも反映しない、意味のないコードなのです。
それゆえにJITによって処理が捨てられ、そのために劇的に高速になったのだろうと疑ってみました。
総和をちゃんと呼び出し側に返すように、改修前で使っていたIntConsumerをIntFunctionに変更します。
次は、改修後のプログラムです。
Lambda1.java
import java.util.function.IntFunction;
public class Lambda1 {
private static final int SIZE = 1_000_000;
void process() {
final IntFunction<Integer> c = i -> sum();
//warming up
for(int i=10000; i>0; i--){
c.apply(0);
sum();
}
//Call via lambda
long start = System.nanoTime();
for(int i=100; i>0; i--){
int sum = c.apply(0);
if(i==1){
System.out.println("sum="+sum);
}
}
long end = System.nanoTime();
printResult("000", end - start);
//Call directly
start = System.nanoTime();
for(int i=100; i>0; i--){
int sum = sum();
if(i==1){
System.out.println("sum="+sum);
}
}
end = System.nanoTime();
printResult("001", end - start);
}
private int sum() {
int sum = 0;
for (int i = 0; i <= SIZE; i++) {
sum += i;
}
return sum;
}
private void printResult(String prefix, long time) {
System.err.println(prefix + ": elapsed=" + time / 1_000);
}
public static void main(String[] args) {
new Lambda1().process();
}
}
測定結果
000: elapsed=144041
001: elapsed=141805
まとめ
Lambdaを経由して呼び出すメソッドの性能が向上するという話はウソでしょう。
スミマセンでした(^^;