Java8的StreamAPI的功能终究怎么呢

时间:2020-04-06 08:58:10  阅读:3119+ 出处:自媒体 作者:奔驰GLC级 责任编辑:奔驰GLC级

  • 作者:Carpenter Lee
  • github.com/CarpenterLee/JavaLambdaInternals
Stream Performance

现已对 Stream API 的用法宣扬够多了,用起简练直观,但功能终究怎么样呢?会不会有很高的功能丢失?本节咱们对 Stream API 的功能一探终究。

为确保测验成果真实可信,咱们将 JVM 运转在 -server形式下,测验数据在 GB 量级,测验机器选用常见的商用服务器,装备如下:

OS CentOS 6.7 x86_64
CPU Intel Xeon X5675, 12M Cache 3.06 GHz, 6 Cores 12 Threads
内存 96GB
JDK java version 1.8.0_91, Java HotSpot(TM) 64-Bit Server VM
测验办法和测验数据

功能测验并不是简略的事,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,测验成果如下图:

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

  1. 关于根本类型 Stream 串行迭代的功能开支显着高于外部迭代开支(两倍);
  2. Stream 并行迭代的功能比串行迭代和外部迭代都好。

并行迭代功能跟可利用的核数有关,上图中的并行迭代运用了悉数 12 个核,为调查运用核数对功能的影响,咱们专门测验了不同核数下的 Stream 并行迭代作用:

剖析,关于根本类型:

  1. 运用 Stream 并行 API 在单核状况下功能很差,比 Stream 串行 API 的功能还差;
  2. 跟着运用核数的添加,Stream 并行作用逐步变好,比运用 for 循环外部迭代的功能还好。

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

试验二 目标迭代

再来看目标的迭代作用。

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

测验程序 StringTest,测验成果如下图:

成果剖析如下:

  1. 关于目标类型 Stream 串行迭代的功能开支依然高于外部迭代开支(1.5 倍),但距离没有根本类型那么大。
  2. Stream 并行迭代的功能比串行迭代和外部迭代都好。

再来独自调查 Stream 并行迭代作用:

剖析,关于目标类型:

  1. 运用 Stream 并行 API 在单核状况下功能比 for 循环外部迭代差;
  2. 跟着运用核数的添加,Stream 并行作用逐步变好,多核带来的作用显着。

以上两个测验阐明,关于目标类型的简略迭代,Stream 串行迭代功能更差,但多核状况下 Stream 迭代时功能较好。

试验三 杂乱目标归约

从试验一、二的成果来看,Stream 串行履行的作用都比外部迭代差(许多),是不是阐明 Stream 真的不行了?先别下定论,咱们再来调查一下更杂乱的操作。

测验内容:给定订单列表,计算每个用户的总交易额。比照运用外部迭代手动完成和 Stream API 之间的功能。

咱们将订单简化为 <userName,price,timeStamp>构成的元组,并用 Order目标来表明。测验程序 ReductionTest,测验成果如下图:

剖析,关于杂乱的归约操作:

  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 类库做了晋级优化,代码不用做任何修正就能享受到晋级带来的优点。

(完)

“如果发现本网站发布的资讯影响到您的版权,可以联系本站!同时欢迎来本站投稿!