java Lambda 与匿名类之间的巨大执行时间差异
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19001241/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Big execution time difference between java Lambda vs Anonymous class
提问by Dewfy
I was curious about performance of creation of java8 lambda instances against the same anonymous class. (Measurement performed on win32 java build 1.8.0-ea-b106). I've created very simple example and measured if java propose some optimization of new
operator while create lambda expression:
我很好奇针对同一个匿名类创建 java8 lambda 实例的性能。(在 win32 java build 1.8.0-ea-b106 上执行的测量)。我创建了非常简单的示例,并测量了 javanew
在创建 lambda 表达式时是否建议对运算符进行一些优化:
static final int MEASURES = 1000000;
static interface ICallback{
void payload(int[] a);
}
/**
* force creation of anonymous class many times
*/
static void measureAnonymousClass(){
final int arr[] = {0};
for(int i = 0; i < MEASURES; ++i){
ICallback clb = new ICallback() {
@Override
public void payload(int[] a) {
a[0]++;
}
};
clb.payload(arr);
}
}
/**
* force creation of lambda many times
*/
static void measureLambda(){
final int arr[] = {0};
for(int i = 0; i < MEASURES; ++i){
ICallback clb = (a2) -> {
a2[0]++;
};
clb.payload(arr);
}
}
(Full code can be taken there: http://codepad.org/Iw0mkXhD) The result is rather predictable - lambda wins 2 times.
(完整代码可以在那里获取:http: //codepad.org/Iw0mkXhD)结果相当可预测 - lambda 赢了 2 次。
But really little shift to make closureshows very bad time for lambda. Anonymous class wins 10 times! So now anonymous class looks like:
但是对于 lambda 来说,关闭闭包的转变真的很糟糕。匿名类获胜 10 次!所以现在匿名类看起来像:
ICallback clb = new ICallback() {
@Override
public void payload() {
arr[0]++;
}
};
And lambda does as follow:
而 lambda 的作用如下:
ICallback clb = () -> {
arr[0]++;
};
(Full code can be taken there: http://codepad.org/XYd9Umty) Can anybody explain me why exists so big (bad) difference in handling of closure?
(完整代码可以在那里获取:http: //codepad.org/XYd9Umty)谁能解释一下为什么在处理闭包时存在如此大(坏)的差异?
回答by assylias
UPDATE
更新
A few comments wondering if my benchmark at the bottom was flawed - after introducing a lot of randomness (to prevent the JIT from optimising too much stuff), I still get similar results so I tend to think it is ok.
一些评论想知道我在底部的基准是否有缺陷 - 在引入了大量随机性(以防止 JIT 优化太多东西)之后,我仍然得到类似的结果,所以我倾向于认为它是可以的。
In the meantime, I have come across this presentationby the lambda implementation team. Page 16 shows some performance figures: inner classes and closures have similar performance / non-capturing lambda are up to 5x times faster.
与此同时,我看到了 lambda 实现团队的这个演示文稿。第 16 页显示了一些性能数据:内部类和闭包具有相似的性能/非捕获 lambda 最多快 5 倍。
And @StuartMarks posted this very interesting linkwhich dissects lambda performance. The bottom line is that post JIT compilation, lambdas and anonymous classes perform similarly on current Hostpot JVM implementations.
@StuartMarks 发布了这个非常有趣的链接,它剖析了 lambda 性能。最重要的是,后 JIT 编译、lambdas 和匿名类在当前的 Hostpot JVM 实现上表现相似。
YOUR BENCHMARK
您的基准
I have also run your test, as you posted it. The problem is that it runs for as little as 20 ms for the first method and 2 ms for the second. Although that is a 10:1 ratio, it is in no way representative because the measurement time is way too small.
我也运行了你的测试,正如你发布的那样。问题是第一种方法的运行时间仅为 20 毫秒,而第二种方法的运行时间仅为 2 毫秒。虽然这是一个 10:1 的比例,但它没有任何代表性,因为测量时间太短了。
I have then taken modified your test to allow for more JIT warmup and I get similar results as with jmh (i.e. no difference between anonymous class and lambda).
然后我修改了你的测试以允许更多的 JIT 预热,我得到了与 jmh 类似的结果(即匿名类和 lambda 之间没有区别)。
public class Main {
static interface ICallback {
void payload();
}
static void measureAnonymousClass() {
final int arr[] = {0};
ICallback clb = new ICallback() {
@Override
public void payload() {
arr[0]++;
}
};
clb.payload();
}
static void measureLambda() {
final int arr[] = {0};
ICallback clb = () -> {
arr[0]++;
};
clb.payload();
}
static void runTimed(String message, Runnable act) {
long start = System.nanoTime();
for (int i = 0; i < 10_000_000; i++) {
act.run();
}
long end = System.nanoTime();
System.out.println(message + ":" + (end - start));
}
public static void main(String[] args) {
runTimed("as lambdas", Main::measureLambda);
runTimed("anonymous class", Main::measureAnonymousClass);
runTimed("as lambdas", Main::measureLambda);
runTimed("anonymous class", Main::measureAnonymousClass);
runTimed("as lambdas", Main::measureLambda);
runTimed("anonymous class", Main::measureAnonymousClass);
runTimed("as lambdas", Main::measureLambda);
runTimed("anonymous class", Main::measureAnonymousClass);
}
}
The last run takes about 28 seconds for both methods.
两种方法的最后一次运行大约需要 28 秒。
JMH MICRO BENCHMARK
JMH 微型基准
I have run the same test with jmhand the bottom line is that the four methods take as much time as the equivalent:
我用 jmh运行了相同的测试,底线是这四种方法需要的时间与等效方法一样多:
void baseline() {
arr[0]++;
}
In other words, the JIT inlines both the anonymous class and the lambda and they take exactly the same time.
换句话说,JIT 内联匿名类和 lambda 并且它们花费完全相同的时间。
Results summary:
结果总结:
Benchmark Mean Mean error Units
empty_method 1.104 0.043 nsec/op
baseline 2.105 0.038 nsec/op
anonymousWithArgs 2.107 0.028 nsec/op
anonymousWithoutArgs 2.120 0.044 nsec/op
lambdaWithArgs 2.116 0.027 nsec/op
lambdaWithoutArgs 2.103 0.017 nsec/op