Java Stream API性能测试

已经对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类库做了升级优化,代码不用做任何修改就能享受到升级带来的好处。

来源:https://www.cnblogs.com/CarpenterLee/p/6675568.html

Java Stream API性能测试相关推荐

  1. Java Stream API入门篇

    转自:https://www.cnblogs.com/CarpenterLee/p/6545321.html 你可能没意识到Java对函数式编程的重视程度,看看Java 8加入函数式编程扩充多少功能就 ...

  2. go语言如何调用java接口_Go语言实现的Java Stream API

    学习Go语言时实现的集合操作工具库,类似于Java 8 中新增的Stream API.由于Go语言不支持泛型,所以基于反射实现.只用于学习目的,不要用于生产(PS:当然也不会有人用). 集合操作包括生 ...

  3. Java Stream API(一)

    2019独角兽企业重金招聘Python工程师标准>>> Stream是JAVA SE8提供的主要用于处理集合的接口,定义是"从支持数据处理操作的源生成的元素序列" ...

  4. java stream api 对象复制_Java 8新特性之旅:使用Stream API处理集合

    在这篇"Java 8新特性教程"系列文章中,我们会深入解释,并通过代码来展示,如何通过流来遍历集合,如何从集合和数组来创建流,以及怎么聚合流的值. 在之前的文章"遍历.过 ...

  5. stream去重_使用Java Stream API中DistinctBy删除重复数据

    Stream API提供distinct()方法,该方法基于数据Object类的equals()方法返回列表的不同元素.下面先做一个数据Object类,用来发现重复数据: public class L ...

  6. 使用Java Stream API将List按自定义分组规则转换成Map的一个例子

    本文完整测试代码见文末. 测试数据是List里的4个员工对象实例: 根据员工所在的城市进行分组: 结果分成了三组: 第一组的员工在上海: 第二组的员工在成都: 统计每组员工个数: 把员工进行分组,得分 ...

  7. java list 自定义类型转换_使用Java Stream API将List按自定义分组规则转换成Map的一个例子...

    本文完整测试代码见文末. 测试数据是List里的4个员工对象实例: 根据员工所在的城市进行分组: 结果分成了三组: 第一组的员工在上海: 第二组的员工在成都: 统计每组员工个数: 把员工进行分组,得分 ...

  8. Java Stream API进阶篇

    转自:https://www.cnblogs.com/CarpenterLee/p/6550212.html 上一节介绍了部分Stream常见接口方法,理解起来并不困难,但Stream的用法不止于此, ...

  9. Java 8 Stream Api 中的 skip 和 limit 操作

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 1. 前言 Java 8 Stream API 中的sk ...

最新文章

  1. R语言ggplot2可视化散点图(scatter plot)、并在可视化图像的顶部和右边添加边缘直方图(Marginal Histogram)、使用geom_smooth函数基于lm方法拟合数据点之间
  2. 今天安装VisualSVN 不小心删掉了安装目录,再次安装 修改 移除提示UninstallWMISchemaExecute (0x8004401e) when updating VisualSV
  3. Java笔试题-Listint l = new Listint()
  4. [LCS]半个月的成果,用RTCClient开发的Robot!
  5. ECCV 2018 | 腾讯AI Lab提出视频再定位任务,准确定位相关视频内容
  6. 索尼 android l,家庭影院级音质 索尼Xperia i1参数全曝光
  7. rest风格使用两个变量_为什么要用Rest风格,接口应该怎么定义,除了Rest还可用什么方式写接口的?...
  8. javascript使用_用JavaScript唤醒沉睡的城市
  9. wordpress功能集成(二):基础知识-wordpress钩子(转)
  10. T-SQL Enhancement in SQL Server 2005[下篇]
  11. .Net/C# 实现真正的只读的 Hashtable 类型的属性 (ReadOnly Hashtable Property)
  12. oracle外部结合,浅谈Oracle外部文件
  13. 开课吧9.9元学python靠谱吗-开课吧的python课程怎么样,值得报名吗?
  14. R语言︱H2o深度学习的一些R语言实践——H2o包
  15. 手机应用只清理不够,还要卸载
  16. 常见排序算法整理2(C++实现)
  17. 文本文档怎样改格式为html格式,文本文档格式怎么更改【图解】
  18. VMware Workstation pro无法在Windows上运行的解决方法
  19. TOP Network技术总监Justin:TOP公链已率先实现多层状态分片
  20. Linux系列八-type、alias与history

热门文章

  1. 【Hibernate】Hibernate查询语言HQL详解
  2. 《跟菜鸟学Cisco UC部署实战》-第 0 章 宣传-课件(一共12章,免费)
  3. iOS程序员也要学点算法吧 简单排序之插入排序
  4. 深入学习jQuery的三种常见动画效果
  5. 【python】获取51cto博客的文章列表
  6. MySQL安装错误:/usr/local/mysql/libexec/mysqld: unknown option '--skip-federated'
  7. 零基础如何学好数据分析?
  8. SEED实验系列:ShellShock 攻击实验
  9. 家族关系查询系统程序设计算法思路_【学习笔记】数据库基础 - 查询优化
  10. linux系统正常停机的命令,Linux系统重启命令大全