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

我对同一个匿名类创建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  { a2[0]++; }; clb.payload(arr); } } 

(完整的代码可以在那里: http : //codepad.org/Iw0mkXhD )结果是可预测的 – lambda赢了2次。

但实际上很少转变为关闭显示lambda非常糟糕的时间。 匿名课程赢了10次! 所以现在匿名类看起来像:

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

而lambda的确如下:

 ICallback clb = () -> { arr[0]++; }; 

(可以在那里找到完整的代码: http : //codepad.org/XYd9Umty )任何人都可以解释为什么在处理闭包时存在如此大(差)的差异?

UPDATE

一些评论想知道我的底部基准是否存在缺陷 – 在引入大量随机性(以防止JIT优化太多东西)之后,我仍然得到类似的结果,所以我倾向于认为它没问题。

与此同时,我在lambda实施团队中遇到了这个演示文稿 。 第16页显示了一些性能数据:内部类和闭包具有类似的性能/非捕获lambda的速度提高了5倍。

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


你的基准

当你发布它时,我也运行你的测试。 问题是第一种方法运行时间仅为20 ms,第二种方法运行时间仅为2 ms。 虽然这是10:1的比例,但它绝不具有代表性,因为测量时间太小。

然后我修改了你的测试以允许更多的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); } } 

两种方法的最后一次运行大约需要28秒。


JMH MICRO BENCHMARK

我用jmh运行相同的测试,底线是这四种方法花费的时间与等效时间相同:

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

换句话说,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