有人说“Lambda能让Java程序慢30倍”,你怎么看?

有人说“Lambda能让Java程序慢30倍”,你怎么看?

在上一讲中,我介绍了Java性能问题分析的一些基本思路。但在实际工作中,我们不能仅仅等待性能出现问题再去试图解决,而是需要定量的、可对比的方法,去评估Java应用性能,来判断其是否能够符合业务支撑目标。今天这一讲,我会介绍从Java开发者角度,如何从代码级别判断应用的性能表现,重点理解最广泛使用的基准测试(Benchmark)。

今天我要问你的问题是,有人说“Lambda能让Java程序慢30倍”,你怎么看?

  • 为了让你清楚地了解这个背景,请参考下面的代码片段。在实际运行中,基于Lambda/Stream的版本(lambdaMaxInteger),比传统的for-each版本 (forEachLoopMaxInteger)慢很多

  • // 一个大的ArrayLis,内部是随机的整形数据
    volatile Lis<Integer> integers =// 基准测试1
    public int forEachLoopMaxInteger() {
     int max = Integer.MIN_VALUE;
     for (Integer n : integers) {
    max = Integer.max(max, n);
     }
     return max;
    }
    // 基准测试2
    public int lambdaMaxInteger() {
     return integers.sream().reduce(Integer.MIN_VALUE, (a, b) -> Integer.max(a, b));
    }
    

典型回答

我认为,“Lambda能让Java程序慢30倍”这个争论实际反映了几个方面:

  • 第一,基准测试是一个非常有效的通用手段,让我们以直观、量化的方式,判断程序在特定条件下的性能表现

  • 第二,基准测试必须明确定义自身的范围和目标,否则很有可能产生误导的结果。前面代码片段本身的逻辑就有瑕疵,更多的开销是源于自动装箱、拆箱(auto boxing/unboxing),而不是源自Lambda和Stream,所以得出的初始结论是没有说服力的

  • 第三,虽然Lambda/Stream为Java提供了强大的函数式编程能力,但是也需要正视其局限性:

    • 一般来说,我们可以认为Lambda/Stream提供了与传统方式接近对等的性能,但是如果对于性能非常敏感,就不能完全忽视它在特定场景的性能差异了,例如:初始化的开销
    • Lambda并不算是语法糖,而是一种新的工作机制,在首次调用时,JVM需要为其构建CallSite实例。这意味着,如果Java应用启动过程引入了很多Lambda语句,会导致启动过程变慢。其实现特点决定了JVM对它的优化可能与传统方式存在差异
    • 增加了程序诊断等方面的复杂性,程序栈要复杂很多,Fluent风格本身也不算是对于调试非常友好的结构,并且在可检查异常的处理方面也存在着局限性等

考点分析

  • 今天的题目是源自于一篇有争议的文章,原文后来更正为“如果Stream使用不当,会让你的代码慢5倍”。针对这个问题我给出的回答,并没有纠结于所谓的“快”与“慢”,而是从工程实践的角度指出了基准测试本身存在的问题,以及Lambda自身的局限性
  • 从知识点的角度,这个问题考察了我在专栏第7讲中介绍过的自动装箱/拆箱机制对性能的影响,并且考察了Java 8中引入的Lambda特性的相关知识。除了这些知识点,面试官还可能更加深入探讨如何用基准测试之类的方法,将含糊的观点变成可验证的结论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IT枫斗者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值