fork join框架

Fork / Join框架在不同配置下如何工作?

就像即将到来的《星球大战》(Star Wars)一样,围绕Java 8并行性的批评也充满了兴奋。 并行流的语法糖带来了一些炒作,就像我们在预告片中看到的新型光剑一样。 现在,有了许多使用Java进行并行处理的方法,我们希望了解性能优势和并行处理的危险。 经过260多次测试运行后,从数据中获得了一些新见解,我们希望在本文中与您分享。

分叉/加入:分叉唤醒

ExecutorService与Fork / Join Framework与并行流

很久以前,在一个遥远的星系中……。 我的意思是,大约10年前,并发只能通过3rd party库在Java中使用。 随后出现了Java 5,并在语言中引入了java.util.concurrent库,该库在Doug Lea的强烈影响下。 ExecutorService可用并为我们提供了一种处理线程池的直接方法。 当然,java.util.concurrent一直在发展,并且在Java 7中引入了Fork / Join框架,该框架建立在ExecutorService线程池之上。 使用Java 8流,已经为我们提供了使用Fork / Join的简单方法,但对于许多开发人员来说仍然有点谜。 让我们找出它们之间的比较。

我们完成了两项任务,一项是CPU密集型任务,另一项是IO密集型任务,并使用相同的基本功能测试了4种不同的方案。 另一个重要因素是我们用于每个实现的线程数,因此我们也对其进行了测试。 我们使用的机器有8个内核 ,因此我们有4、8、16和32个线程的变种,以大致了解结果的发展方向。 对于每个任务,我们还尝试了单线程解决方案,您不会在图中看到它,因为执行起来要花费更长的时间。 要详细了解测试的运行方式,您可以查看下面的基础部分。 现在,让我们开始吧。

用580万行文本索引6GB文件

在此测试中,我们生成了一个巨大的文本文件,并为索引过程创建了类似的实现。 结果如下所示:

文件索引测试结果

**单线程执行:176,267毫秒,或将近3分钟。
**请注意,图形开始于20000毫秒。

1.更少的线程将使CPU未被使用,太多的线程将增加开销

您在图表中注意到的第一件事是结果开始采用的形状–您仅从这4个数据点就可以了解每个实现的行为。 临界点在8到16个线程之间,因为某些线程在文件IO中处于阻塞状态,并且添加比内核更多的线程有助于更好地利用它们。 当有32个线程进入时,由于额外的开销,性能会变差。

比亚军快1秒:直接使用Fork / Join

除了语法糖(lambdas!我们没有提到lambdas),我们已经看到并行流的性能比Fork / Join和ExecutorService实现的更好。 6GB的文本在24.33秒内被索引。 您可以在这里信任Java来提供最佳结果。

3.但是…并行流也表现最差:唯一的变化超过了30秒

这再次提醒您并行流如何降低您的速度。 假设这种情况发生在已经运行多线程应用程序的计算机上。 在可用线程数量较少的情况下,直接使用Fork / Join实际上比通过并行流要好-5秒的差异,将这两个线程进行比较时大约要付出18%的代价。

4.不要使用图片中带有IO的默认池大小

当为并行流使用默认池大小时,机器上相同数量的内核(此处为8个内核)比16线程版本的性能差了近2秒。 如果使用默认池大小,则要加收7%的罚款。 发生这种情况的原因与阻塞IO线程有关。 还有更多的等待正在进行,因此引入更多的线程可以使我们更多地使用所涉及的CPU内核,而其他线程可以等待调度而不是空闲。

如何更改并行流的默认Fork / Join池大小? 您可以使用JVM参数更改常见的Fork / Join池大小:

-Djava.util.concurrent.ForkJoinPool.common.parallelism=16

(默认情况下,所有Fork / Join任务都使用一个公共静态池,其大小与内核数相同。这样做的好处是,通过在不使用期间为其他任务回收线程,从而减少了资源使用。)

或者…您可以使用此技巧并在自定义Fork / Join池中运行并行流。 这将覆盖通用的Fork / Join池的默认用法,并允许您使用自己设置的池。 偷偷摸摸。 在测试中,我们使用了公共池。

5.单线程性能比最佳结果差7.25倍

并行性提供了7.25倍的改进,并且考虑到该机器具有8个内核,因此非常接近理论上的8倍预测! 我们可以将其余的归因于开销。 话虽如此,即使我们测试的最慢的并行性实现(这次是具有4个线程的并行流(30.24sec)),其性能也比单线程解决方案(176.27sec)好5.8倍。

检查数字是否为质数

在下一轮测试中,我们完全消除了IO,并检查了确定一个真正大的数字是否为素数所需的时间。 多大? 19位数字 。 1,530,692,068,127,007,263或换句话说:五百一十九亿四千三百四十四万亿三千三百八十亿八千八百八十三万三千三百三十。 啊,让我呼吸一下。 无论如何,除了运行到其平方根之外,我们没有使用任何优化,因此即使我们的大数没有除以2只是为了延长处理时间,我们也检查了所有偶数。 剧透警告:这是首要的,因此每个实现都运行相同数量的计算。

结果是这样的:

素数测试结果

**单线程执行:118,127毫秒,或将近2分钟。
**请注意,图形开始于20000毫秒

1. 8和16个线程之间的差异较小

与IO测试不同,这里没有IO调用,因此8和16线程的性能几乎是相似的,除了Fork / Join解决方案。 实际上,我们已经运行了更多的测试集,以确保由于这种“异常”而在这里获得了良好的结果,但事实证明,一次又一次的相似。 我们很高兴在下面的评论部分中听到您对此的想法。

2.所有方法的最佳结果相似

我们看到所有实现都分享了大约28秒的相似最佳结果。 无论我们尝试采用哪种方法,结果都相同。 这并不意味着我们对使用哪种方法都无所谓。 查看下一个见解。

3.并行流比其他实现更好地处理线程重载

这是更有趣的部分。 通过该测试,我们再次看到运行16个线程的最高结果来自使用并行流。 此外,在此版本中,使用并行流是线程号所有变体的一个好选择。

4.单线程性能比最佳结果低4.2倍

此外,在运行计算密集型任务时使用并行性的好处几乎比使用文件IO的IO测试要差2倍。 这是有道理的,因为它是CPU密集型测试,与之前的测试不同,我们可以通过减少内核等待被IO阻塞的线程的时间来获得额外的好处。

结论

我建议您从源头上了解何时使用并行流的更多信息,并在您使用Java进行并行化时随时进行仔细的判断。 最好的方法是在暂存环境中运行与这些测试类似的测试,在此环境中您可以尝试并更好地了解要面对的挑战。 您必须注意的因素当然是运行的硬件(以及要测试的硬件)以及应用程序中的线程总数。 这包括公用的Fork / Join池和团队中其他开发人员正在处理的代码。 因此,在添加自己的并行性之前,请尝试检查它们并获得应用程序的完整视图。

基础工作

为了运行此测试,我们使用了具有8个vCPU和15GB RAM的EC2 c3.2xlarge实例。 vCPU意味着存在超线程,因此实际上我们在这里有4个物理内核,每个物理内核都像2个内核一样工作。就OS调度程序而言,我们在这里有8个内核。 为了尽可能使它公平,每个实现都运行了10次,并且我们采用了运行2到9的平均运行时间。这是260次测试运行,! 另一重要的是处理时间。 我们选择的任务要花费20秒钟以上的时间,因此差异更容易发现,并且不受外部因素的影响。

下一步是什么?

原始结果可在此处获得 ,代码在GitHub上 。 请随时修改它,并让我们知道您得到什么样的结果。 如果您对我们错过的结果有更多有趣的见解或解释,我们很乐意阅读并添加到帖子中。

翻译自: https://www.javacodegeeks.com/2015/01/forkjoin-framework-vs-parallel-streams-vs-executorservice-the-ultimate-forkjoin-benchmark.html

fork join框架

fork join框架_Fork / Join框架vs.并行流vs.ExecutorService:最终的Fork / Join基准相关推荐

  1. Fork / Join框架vs并行流vs.ExecutorService:最终的Fork / Join基准

    Fork / Join框架在不同配置下如何工作? 就像即将上映的<星球大战>一样,围绕Java 8并行性的批评也充满了兴奋. 并行流的语法糖带来了一些炒作,就像我们在预告片中看到的新型光剑 ...

  2. 【Java8新特性 串行/并行流-Optional容器类-时间格式化线程安全等】

    Java8新特性二 一.并行流与顺序流 1.概念 2.Fork/Join框架 3. Fork/Join框架代码示例: 二.Optional类 1. 什么是Optional对象 2. Optional类 ...

  3. stream銆俠oxed_java-11-Stream优化并行流

    并行流    多线程    把一个内容分成多个数据块  不同线程分别处理每个数据块的流 串行流   单线程  一个线程处理所有数据 java8 对并行流优化  StreamAPI 通过parallel ...

  4. 锁与并发工具包与线程池与LockSupport与Fork/Join框架与并行流串行流与阻塞队列与JPS,jstack命令查看死锁查看线程状态与AQS个人笔记九

    朝闻道,夕死可矣 本文共计 86564字,估计阅读时长1小时 点击进入->Thread源码万字逐行解析 文章目录 本文共计 86564字,估计阅读时长1小时 一锁 二Java中13个原子操作类 ...

  5. [python] 3 、基于串口通信的嵌入式设备上位机自动测试程序框架(简陋框架)...

    星期一, 20. 八月 2018 01:53上午 - beautifulzzzz 1.前言 做类似zigbee.ble mesh...无线网络节点性能测试的时候,手动操作然后看表象往往很难找出真正的原 ...

  6. css框架和js框架_如何选择正确CSS工具包和框架

    css框架和js框架 A Q&A about Susy and other toolkits, with Miriam Suzanne. 与Miriam Suzanne一起有关Susy和其他工 ...

  7. java集合框架容器 java框架层级 继承图结构 集合框架的抽象类 集合框架主要实现类...

    本文关键词: java集合框架  框架设计理念  容器 继承层级结构 继承图 集合框架中的抽象类  主要的实现类 实现类特性   集合框架分类 集合框架并发包 并发实现类 什么是容器? 由一个或多个确 ...

  8. SQL的连接(join)有哪些常见形式?解释一下?解释 SQL 的 left join 和 right join?

    SQL的连接(join)有哪些常见形式?解释一下?解释 SQL 的 left join 和 right join? SQL的连接(join)有哪些常见形式? sql连接查询:把多张表的列组合在一起,产 ...

  9. Django之MVC框架与MTV框架详解

    Django框架简介 MVC框架和MTV框架(了解即可) MVC,全名是Model View Controller,是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model).视图 ...

最新文章

  1. 【PAT (Advanced Level) Practice】1002 A+B for Polynomials (25 分)
  2. windows下实现Git在局域网使用
  3. 030_CSS外边距合并
  4. InnoDB与MyISAM的六大区别(转)
  5. Android开发之动画(转)
  6. javascript:void(0) 含义
  7. Android 人脸照片对比,人脸对比
  8. 行向量,列向量,行主序矩阵,列主序矩阵
  9. 修改所有列_哪些数据库是行存储?哪些是列存储?有什么区别?
  10. tocmat linux搭建测试环境,Apache+Tomcat 环境搭建(JK部署过程)
  11. VMware 虚拟化平台规划设计方案
  12. QQ和微信使用到的网络协议
  13. java 获取项目下的webapp_Spring Boot2 系列教程(一)纯 Java 搭建 SSM 项目
  14. 平面方程、夹角与点到平面的距离
  15. 母婴群如何引流?孕妈群如何引流?母婴群怎么运营好?
  16. 100天python、github_GitHub - 100440175/Python-100-Days: Python - 100天从新手到大师
  17. mysql数据库用sql语句在指定的一个字段后面添加一个字段
  18. 【纪中受难记】——Day1:没有爆零
  19. 《零基础入门学习Python》(23)--递归:这帮小兔崽子
  20. mysql 根据某一年 查询12个月的数据

热门文章

  1. 学习手记(2020/8/19~2021/3/19)
  2. 【2018.5.19】模拟赛之一-ssl2432 面积最大【数学】
  3. 【DP】【高精】逆序对(jzoj 2014)
  4. 【二分】抄书 (jzoj 2123)
  5. HDU5875 - Function
  6. 案例分析 | 由Decimal操作计算引发的Spark数据丢失问题
  7. 企业级负载均衡如何实现
  8. Oracle入门(十四.17)之procedure传递参数
  9. 面象对象设计6大原则之三:里氏替换原则
  10. 【双11劲爆干货】阿里高级Java面试题(首发,70道)