java Lambda和匿名类之间的大执行时间差异 [英] Big execution time difference between java Lambda vs Anonymous class

查看:176
本文介绍了java Lambda和匿名类之间的大执行时间差异的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对于针对同一个匿名类创建java8 lambda实例的性能感到好奇。 (在win32 java build 1.8.0-ea-b106上执行的测量)。我创建了一个非常简单的例子,并测量如果java提出一些优化 new 运算符,同时创建lambda表达式:

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:

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);
    }
}

=http://codepad.org/Iw0mkXhD> http://codepad.org/Iw0mkXhD )结果相当可预测 - 拉姆斯胜过2次。

(Full code can be taken there: http://codepad.org/Iw0mkXhD) The result is rather predictable - lambda wins 2 times.

但真的很少转向关闭显示lambda的非常糟糕的时间。匿名班赢得10倍!
现在匿名类看起来像:

But really little shift to make closure shows very bad time for lambda. Anonymous class wins 10 times! So now anonymous class looks like:

ICallback clb = new ICallback() {
        @Override
        public void payload() {
            arr[0]++;
        }
    };

而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?

推荐答案

UPDATE



一些评论想知道我的基准是否有缺陷 - 在引入了很多随机性防止JIT优化太多的东西),我仍然得到类似的结果,所以我倾向于认为它是确定。

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.

在此期间,我遇到了这个演示文稿由lambda实现团队完成。第16页显示了一些性能数据:内部类和闭包有类似的性能/非捕获lambda是高达5倍的速度。

In the meantime, I have come across this presentation by 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.

和@StuartMarks发布了非常有趣的链接,它解剖lambda性能。底线是后JIT编译,lambdas和匿名类在当前Hostpot JVM实现上执行类似。

And @StuartMarks posted this very interesting link which dissects lambda performance. The bottom line is that post JIT compilation, lambdas and anonymous classes perform similarly on current Hostpot JVM implementations.

我也运行你的测试,因为你发布它。问题是,对于第一种方法,它运行时间最短为20 ms,第二种方法运行时间为2 ms。虽然这是一个10:1的比例,它是没有代表性,因为测量时间太小。

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.

我已经修改了你的测试,以允许更多JIT warmup和我得到类似的结果与jmh(即匿名类和lambda之间没有区别)。

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).

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);
    }
}

上次运行大约需要28秒。

The last run takes about 28 seconds for both methods.

=https://bitbucket.org/assylias/performance/src/09e3902b1396f44555b59741cd243fe97888f1cd/src/main/java/com/assylias/performance/SO19001241_Closures.java>与jmh 的测试相同,底线是这四种方法需要的时间等同于:

I have run the same test with jmh and the bottom line is that the four methods take as much time as the equivalent:

void baseline() {
    arr[0]++;
}

换句话说,JIT嵌入了匿名类和lambda,

In other words, the JIT inlines both the anonymous class and the lambda and they take exactly the same time.

结果摘要:

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

这篇关于java Lambda和匿名类之间的大执行时间差异的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆