Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/google-cloud-platform/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
java Lambda与匿名类之间的执行时间差异很大_Java_Performance_Lambda_Closures_Java 8 - Fatal编程技术网

java Lambda与匿名类之间的执行时间差异很大

java Lambda与匿名类之间的执行时间差异很大,java,performance,lambda,closures,java-8,Java,Performance,Lambda,Closures,Java 8,我对针对同一匿名类创建java8 lambda实例的性能感到好奇。(在win32 java build 1.8.0-ea-b106上执行的测量)。我创建了一个非常简单的示例,并测量了java在创建lambda表达式时是否对new运算符进行了一些优化: static final int MEASURES = 1000000; static interface ICallback{ void payload(int[] a); } /** * force creation of anonym

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

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);
    }
}
lambda的做法如下:

ICallback clb = () -> {
            arr[0]++;
        };
(完整代码可在此处获取:) 有人能解释一下为什么在处理闭包时存在如此大(糟糕)的差异吗?

UPDATE 一些评论怀疑我在底部的基准是否有缺陷——在引入了很多随机性(防止JIT优化太多东西)之后,我仍然得到类似的结果,所以我倾向于认为这是可以的

同时,我遇到了lambda实施团队。第16页显示了一些性能数据:内部类和闭包具有相似的性能/不捕获lambda的速度高达5倍

@StuartMarks发布了这个。归根结底,JIT编译后,lambdas和匿名类在当前Hostpot JVM实现上的性能类似


你的基准 我也运行了你的测试,正如你发布的一样。问题是第一种方法的运行时间只有20毫秒,第二种方法只有2毫秒。虽然这是一个10:1的比率,但它并不具有代表性,因为测量时间太小了

然后,我对您的测试进行了修改,以允许更多的JIT预热,我得到了与jmh类似的结果(即匿名类和lambda之间没有区别)

换句话说,JIT内联了匿名类和lambda,它们占用的时间完全相同

结果摘要:

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

这是一种相当幼稚的微基准方法。至少使用
System.nanoTime
并引入一次性执行来预热JVM。在执行之间调用几个
System.gc()
也是个好主意。理想情况下,使用Google Caliper或Oracle jmh执行此操作。@MarkoTopolnik-事实上我已经预见到了这一点,这就是为什么我在
measureLambda
首先运行时执行了两次测量,而
measureambda
measureAnonymousClass
之后运行时执行了两次测量,根本没有任何影响!纳米时间可以显示精确测量的差异,但当我谈论10倍时,它的精度通常为十分之一秒(取决于平台)。
nanoTime
的精度通常为微秒级。而且,仅仅重新排序执行并不能证明什么:每个代码路径都必须自己预热。预热执行是实现这一点的方法,垃圾收集必须加以控制。也许你没有抓住我目前评论的要点:在JVM上进行基准测试时,它伪造了一些关于常见错误源的标准假设。只有当你彻底清除了这些数据之后,你才能对结果进行认真的讨论。请注意,除了这个基准远离预期用例之外,只要在JVM启动时指定
-server
选项,记录的开销就会完全消失。这意味着JIT完全消除了实际lambda/匿名类实例的分配。然而,如果OP有不同的结果,那么我将按照描述进行:将分配与调用分开,看看差异是否仍然存在。无论如何,我非常确定OP的巨大差异是由于一个代码路径具有EA的优势,而另一个代码路径经过完整的动态分配。我看不到任何其他因素可以解释10或更多。谢谢你写下你的绩效调查+1.lambda最初(大部分是原型)的JDK 8实现正是一个匿名的内部类,目的是让某些东西尽早工作,以便我们能够探索语言和库的演变。这似乎催生了一个神话,认为lambda只不过是匿名的内部类。最近,对实现进行了优化,使lambda几乎总是比“等效”匿名内部类快。此外,性能专家还进行了两次伟大的JVM语言峰会。首先,Alexey Shipilev(jmh的作者)谈到了基准测试及其许多缺陷。(这被评为今年JVMLS的最佳演讲。)其次,谢尔盖·库克森科谈到了他为优化兰博达的表现所做的工作。[1] [2]@Tuntable链接已更新。谢谢你提到这件事。
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);
    }
}
void baseline() {
    arr[0]++;
}
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