作者:CarpenterLee

来源:https://github.com/CarpenterLee

已经对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对性能的影响有两方面:
  • GC的影响。GC的行为是Java中很不好控制的一块,为增加确定性,我们手动指定使用CMS收集器,并使用10GB固定大小的堆内存。具体到JVM参数就是-XX:+UseConcMarkSweepGC -Xms10G -Xmx10G
  • JIT(Just-In-Time)即时编译技术。即时编译技术会将热点代码在JVM运行的过程中编译成本地代码,测试时我们会先对程序预热,触发对测试函数的即时编译。相关的JVM参数是-XX:CompileThreshold=10000
Stream并行执行时用到ForkJoinPool.commonPool()得到的线程池,为控制并行度我们使用Linux的taskset命令指定JVM可用的核数。
测试数据由程序随机生成。为防止一次测试带来的抖动,测试4次求出平均时间作为运行时间。

实验一 基本类型迭代

测试内容:找出整型数组中的最小值。对比for循环外部迭代和Stream API内部迭代性能。
测试程序IntTest,测试结果如下图:

图中展示的是for循环外部迭代耗时为基准的时间比值。分析如下:
  • 对于基本类型Stream串行迭代的性能开销明显高于外部迭代开销(两倍);
  • Stream并行迭代的性能比串行迭代和外部迭代都好。
并行迭代性能跟可利用的核数有关,上图中的并行迭代使用了全部12个核,为考察使用核数对性能的影响,我们专门测试了不同核数下的Stream并行迭代效果:分析,对于基本类型:
  • 使用Stream并行API在单核情况下性能很差,比Stream串行API的性能还差;
  • 随着使用核数的增加,Stream并行效果逐渐变好,比使用for循环外部迭代的性能还好。
以上两个测试说明,对于基本类型的简单迭代,Stream串行迭代性能更差,但多核情况下Stream迭代时性能较好。

实验二 对象迭代

再来看对象的迭代效果。
测试内容:找出字符串列表中最小的元素(自然顺序),对比for循环外部迭代和Stream API内部迭代性能。
测试程序StringTest,测试结果如下图:

结果分析如下:
  • 对于对象类型Stream串行迭代的性能开销仍然高于外部迭代开销(1.5倍),但差距没有基本类型那么大。
  • Stream并行迭代的性能比串行迭代和外部迭代都好。
再来单独考察Stream并行迭代效果:

分析,对于对象类型:
  • 使用Stream并行API在单核情况下性能比for循环外部迭代差;
  • 随着使用核数的增加,Stream并行效果逐渐变好,多核带来的效果明显。

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

实验三 复杂对象归约

从实验一、二的结果来看,Stream串行执行的效果都比外部迭代差(很多),是不是说明Stream真的不行了?先别下结论,我们再来考察一下更复杂的操作。
测试内容:给定订单列表,统计每个用户的总交易额。对比使用外部迭代手动实现和Stream API之间的性能。
我们将订单简化为<userName, price, timeStamp>构成的元组,并用Order对象来表示。测试程序ReductionTest,测试结果如下图:

分析,对于复杂的归约操作:
  1. Stream API的性能普遍好于外部手动迭代,并行Stream效果更佳;

再来考察并行度对并行效果的影响,测试结果如下:

分析,对于复杂的归约操作:
  • 使用Stream并行归约在单核情况下性能比串行归约以及手动归约都要差,简单说就是最差的;
  • 随着使用核数的增加,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类库做了升级优化,代码不用做任何修改就能享受到升级带来的好处。
推荐阅读 ↓↓↓

2

3

4

5

6

7

8

一个人学习、工作很迷茫?

为什么我推荐你立刻使用Java 8 Stream?性能逆天了相关推荐

  1. java 8 stream 性能_java8中parallelStream性能测试及结果分析

    测试1 @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.NANOSECONDS) @Warmup(iterations = 5, t ...

  2. 推荐十个最好的Java性能故障排除工具:

    推荐十个最好的Java性能故障排除工具: 1.jconsole是随着JDK 1.5而推出的.这是一个Java监测和管理控制台-JMX兼容的图形工具来监测Java虚拟机.它能够同时监测本地和远程的JVM ...

  3. SSM毕设项目毕业生就业推荐平台s0m59(java+VUE+Mybatis+Maven+Mysql)

    SSM毕设项目毕业生就业推荐平台s0m59(java+VUE+Mybatis+Maven+Mysql) 项目运行 环境配置: Jdk1.8 + Tomcat8.5 + Mysql + HBuilder ...

  4. 基于ssm美食推荐管理系统获取(java毕业设计)

    基于ssm美食推荐管理系统 美食推荐管理系统是基于java编程语言,ssm框架,mysql数据库开发,本系统主要分为用户和管理员两个角色,其中用户注册登陆后可以查看美食,教程,社区,资讯公告,收藏,评 ...

  5. 在外包公司从 Java 后端干到安卓开发,你醒醒吧,阿里大师推荐的这份 Java 开发必读书单

    先是工作内容的问题. 当初他应聘的岗位是后端开发,可现实却是他既要写后端,也要写客户端.本着做的多做的广可以学到更多的原则,他并不是非常在意这个问题,边做边学,渐渐地也上了手. 其次是工作量的问题. ...

  6. Java Reactor Stream

    一.Reactor 概念/POM 更多内容,前往 IT-BLOG "具有非阻塞负压功能的异步流处理系统" 的标准以及API.主要用来构建 JVM环境下的非阻塞应用程序.它直接和 J ...

  7. 牛逼哄洪的 Java 8 Stream,性能也牛逼么?

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 Java8的Stream API可以极大提高Java程序员的生产力 ...

  8. Java8 Stream性能如何及评测工具推荐

    点击蓝色"程序猿DD"关注我 回复"资源"获取独家整理的学习资料! 作为技术人员,学习新知识是基本功课.有些知识是不得不学,有些知识是学了之后如虎添翼,Java ...

  9. 一文了解 Java 应用程序性能优化指南

    点击上方"CSDN",选择"置顶公众号" 关键时刻,第一时间送达! 在<2018 最具就业前景的 7 大编程语言>一文中,通过分析了来自 Indee ...

  10. Java 8 Stream流 的用法

    Java 8 Stream流 什么是 Stream? Stream(流)是一个来自数据源的元素队列并支持聚合操作 元素是特定类型的对象,形成一个队列. Java中的Stream并不会存储元素,而是按需 ...

最新文章

  1. RabbitMQ入门(4)--路由
  2. php session 跨子域和跨服务器解决方式
  3. Java项目目录结构与解析
  4. GitLab CI持续集成配置方案
  5. monogdb操作system.*权限
  6. react(87)--控制禁用disabled
  7. MySql-phpMyAdmin
  8. 创龙DSP6748开发板驱动LCD屏
  9. MyBatis:学习笔记(4)——动态SQL
  10. 【SpringCloud】Spring cloud Alibaba Sentinel @SentinelResource
  11. 小团队适合引入 Spring Cloud 微服务吗?
  12. koreader下载_kindle koreader
  13. couchbase php,轻松搞定|将PHP和Couchbase应用部署为Docker
  14. java 拖拉机_Java——io流
  15. 一篇文章带你搞定 SpringBoot 配合 SpringSecurity 实现自动登录功能
  16. 融合软泥怪 (优先队列)
  17. 什么是HashMap?不同版本的HashMap有什么不同?浅谈HashMap
  18. JAVA社招面试问题总结(一年工作经验)
  19. ping指令的格式及参数
  20. [Codeforces Round #373 DIV1E (CF718E)] Matvey's Birthday

热门文章

  1. SmartRoute之远程接口调用和负载
  2. Remoting示例
  3. 利用bootstrap的modal组件自定义alert,confirm和modal对话框
  4. outlook与shairepoint2010 数据同步
  5. VMWare网络连接方式与设置
  6. hdu 4908 BestCoder Sequence
  7. media encoder中文2022已上线
  8. 苹果mac矢量图形设计软件:Illustrator
  9. Mac菜单栏使用过程中遇到的问题及解决方法
  10. SmartSVN 14 for Mac(多平台SVN客户端)