关于java:牛逼哄洪的-Java-8-Stream性能也牛逼么

42次阅读

共计 2602 个字符,预计需要花费 7 分钟才能阅读完成。

作者:CarpenterLee
https://github.com/CarpenterL…

Java8 的 Stream API 能够极大进步 Java 程序员的生产力,让程序员写出高效率、洁净、简洁的代码。

那么,Stream API 的性能到底如何呢,代码整洁的背地是否意味着性能的损耗呢?本文对 Stream API 的性能一探到底。

为保障测试后果真实可信,咱们将 JVM 运行在 -server 模式下,测试数据在 GB 量级,测试机器采纳常见的商用服务器,配置如下:

测试所用代码在这里

https://github.com/CarpenterL…

测试后果汇总

https://github.com/CarpenterL…

测试方法和测试数据

性能测试并不是容易的事,Java 性能测试更吃力,因为虚拟机对性能的影响很大,JVM 对性能的影响有两方面:

1、GC 的影响。GC 的行为是 Java 中很不好管制的一块,为减少确定性,咱们手动指定应用 CMS 收集器,并应用 10GB 固定大小的堆内存。个体到 JVM 参数就是 -XX:+UseConcMarkSweepGC-Xms10G-Xmx10G

2、JIT(Just-In-Time) 即时编译技术。即时编译技术会将热点代码在 JVM 运行的过程中编译成本地代码,测试时咱们会先对程序预热,触发对测试函数的即时编译。相干的 JVM 参数是 -XX:CompileThreshold=10000

Stream 并行执行时用到 ForkJoinPool.commonPool() 失去的线程池,为管制并行度咱们应用 Linux 的 taskset 命令指定 JVM 可用的核数。

测试数据由程序随机生成。为避免一次测试带来的抖动,测试 4 次求出均匀工夫作为运行工夫。

试验一 根本类型迭代

测试内容:找出整型数组中的最小值。比照 for 循环内部迭代和 Stream API 外部迭代性能。

测试程序 IntTest

https://github.com/CarpenterL…

测试后果如下图:

图中展现的是 for 循环内部迭代耗时为基准的工夫比值。剖析如下:

1、对于根本类型 Stream 串行迭代的性能开销显著高于内部迭代开销(两倍);

2、Stream 并行迭代的性能比串行迭代和内部迭代都好。

并行迭代性能跟可利用的核数无关,上图中的并行迭代应用了全副 12 个核,为考查应用核数对性能的影响,咱们专门测试了不同核数下的 Stream 并行迭代成果:

剖析,对于根本类型:

1、应用 Stream 并行 API 在单核状况下性能很差,比 Stream 串行 API 的性能还差;

2、随着应用核数的减少,Stream 并行成果逐步变好,比应用 for 循环内部迭代的性能还好。

以上两个测试阐明,对于根本类型的简略迭代,Stream 串行迭代性能更差,但多核状况下 Stream 迭代时性能较好。

试验二 对象迭代

再来看对象的迭代成果。

测试内容:找出字符串列表中最小的元素(天然程序),比照 for 循环内部迭代和 Stream API 外部迭代性能。

测试程序 StringTest

https://github.com/CarpenterL…

对 Stream 不相熟的,能够关注微信公众号:Java 技术栈,在后盾回复:Java。

测试后果如下图:

后果剖析如下:

1、对于对象类型 Stream 串行迭代的性能开销依然高于内部迭代开销(1.5 倍),但差距没有根本类型那么大。

2、Stream 并行迭代的性能比串行迭代和内部迭代都好。

再来独自考查 Stream 并行迭代成果:

剖析,对于对象类型:

1、应用 Stream 并行 API 在单核状况下性能比 for 循环内部迭代差;

2、随着应用核数的减少,Stream 并行成果逐步变好,多核带来的成果显著。

以上两个测试阐明,对于对象类型的简略迭代,Stream 串行迭代性能更差,但多核状况下 Stream 迭代时性能较好。

试验三 简单对象归约

从试验一、二的后果来看,Stream 串行执行的成果都比内部迭代差(很多),是不是阐明 Stream 真的不行了?先别下结论,咱们再来考查一下更简单的操作。

测试内容:给定订单列表,统计每个用户的总交易额。比照应用内部迭代手动实现和 Stream API 之间的性能。

咱们将订单简化为 <userName,price,timeStamp> 形成的元组,并用 Order 对象来示意。测试程序 ReductionTest

https://github.com/CarpenterL…

测试后果如下图:

剖析,对于简单的归约操作:

1、Stream API 的性能广泛好于内部手动迭代,并行 Stream 成果更佳;

再来考查并行度对并行成果的影响,测试后果如下:

剖析,对于简单的归约操作:

1、应用 Stream 并行归约在单核状况下性能比串行归约以及手动归约都要差,简略说就是最差的;

2、随着应用核数的减少,Stream 并行成果逐步变好,多核带来的成果显著。

以上两个试验阐明,对于简单的归约操作,Stream 串行归约成果好于手动归约,在多核状况下,并行归约成果更佳。咱们有理由置信,对于其余简单的操作,Stream API 也能体现出类似的性能体现。

论断

上述三个试验的后果能够总结如下:

1、对于简略操作,比方最简略的遍历,Stream 串行 API 性能显著差于显示迭代,但并行的 Stream API 可能施展多核个性。

2、对于简单操作,Stream 串行 API 性能能够和手动实现的成果匹敌,在并行执行时 Stream API 成果远超手动实现。

所以,如果出于性能思考

1、对于简略操作举荐应用内部迭代手动实现

2、对于简单操作,举荐应用 Stream API

3、在多核状况下,举荐应用并行 Stream API 来施展多核优势,

4、单核状况下不倡议应用并行 Stream API。

如果出于代码简洁性思考,应用 Stream API 可能写出更短的代码。即便是从性能方面说,尽可能的应用 Stream API 也另外一个劣势,那就是只有 Java Stream 类库做了降级优化,代码不必做任何批改就能享受到降级带来的益处。

近期热文举荐:

1.600+ 道 Java 面试题及答案整顿 (2021 最新版)

2. 终于靠开源我的项目弄到 IntelliJ IDEA 激活码了,真香!

3. 阿里 Mock 工具正式开源,干掉市面上所有 Mock 工具!

4.Spring Cloud 2020.0.0 正式公布,全新颠覆性版本!

5.《Java 开发手册(嵩山版)》最新公布,速速下载!

感觉不错,别忘了顺手点赞 + 转发哦!

正文完
 0