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

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

就像即将上映的《星球大战》一样,围绕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中,在ExecutorService线程池的基础上引入了Fork / Join框架。 借助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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/361136.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CSRF攻击与防御

CSRF是什么 CSRF在百度百科中是这么说的:“CSRF(Cross-site request forgery跨站请求伪造,也被称为“one click attack”或者session riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。尽管听起来像跨站脚本&a…

Silverlight学习笔记(九)-----RenderTransform特效【五种基本变换】及【矩阵变换MatrixTransform】...

RenderTransform特效: 变形(RenderTransform)类是为了达到直接去改变某个Silverlight对象的形状(比如缩放、旋转一个元素)的目的而设计的,RenderTransform包含的变形属性成员就是专门用来改变Silverlight对…

React 篇 Search Bar and content Table

我们要构建一个模块,其中包含一个内容显示的表格,然后上面有一个提供Search的栏位,并对Search中输入栏进行监听,当有改变的时候,触发Search然后对内容表中的内容进行过滤。 Demo Link:http://czrmodel.mybluemix.net/…

PrimeFaces:在动态生成的对话框中打开外部页面

我已经在即将出版的PrimeFaces Cookbook 2版中写了一篇关于食谱的博客。 在这篇文章中,我想发表第二篇关于一个名为Dialog Framework的小型框架的文章。 我个人喜欢它,因为我记得我为使用Struts框架付出同样的努力而付出的代价。 当您想将外部页面加载到…

vue-router之 beforeRouteEnter

beforeRouteEnter在每次路由切换都执行 ,而项目优化后,切换路由mounted只在最开始执行一次beforeRouteEnter的具体用法可参考官方文档 https://cn.vuejs.org/v2/guide/migration-vue-router.html#activate-替换 需要注意的是:在这期间路由跳转携带的数据发生改变会影…

突破极限–如何将AeroGear Unified Push用于Java EE和Node.js

在2014年底的AeroGear队宣布红帽的JBoss统一推送服务器的可用性xPaaS 。 让我们仔细看看! 总览 统一推送服务器允许开发人员将本地推送消息发送到Apple的推送通知服务(APNS)和Google的云消息传递(GCM)。 它具有一个内…

js 获取json数组里面数组的长度

作为一个前端页面开发者第一次处理json数据,遇到了‘js 获取json数组里面数组的长度’?竟然不知道 json没有.length属性(真是要嘲讽下自己),少壮不努力老大徒伤悲啊!以前都是去寻求男朋友帮助,但…

针对WildFly和EAP运行Java Mission Control和Flight Recorder

Java Mission Control (JMC)使您可以监视和管理Java应用程序,而无需引入通常与这些类型的工具相关的性能开销。 它使用为正常的JVM动态优化而收集的数据,从而形成了一种非常轻量级的方法来观察和分析应用程序代码中的问题。 JMC由…

C#堆栈和堆的讲解

OS和CLR通常将用于容纳数据的内存划分为两个独立的区域,每个区域都采用截然不同的方式来管理:堆栈(Stack)和堆(heap)。(1) 调用一个方法时,它的参数以及它的局部变…

jQuery中的常用内容总结(一)

jQuery中的常用内容总结(一) 前言 不好意思(✿◠‿◠),由于回家看病以及处理一些其它事情耽搁了,不然这篇博客本该上上周或者上周写的;同时闲谈几句:在这里建议各位开发的童鞋,如果有疾病尽快治疗,不要拖&a…

线程魔术技巧:Java线程可以做的5件事

Java线程最鲜为人知的事实和用例是什么? 有些人喜欢爬山,有些人喜欢跳伞。 我,我喜欢Java。 我喜欢它的一件事是,您永不停止学习。 您每天使用的工具通常可以向您展示全新的方面,以及您还没有机会看到的方法和有趣的用…

强制删除tfs未迁入项的两个方法。

方法1: 打开Vs2008的命令提示: 查看用户的工作区: 输入: Tf workspaces /owner:所有者或* /server:服务器名称或IP ex: tf workspaces /owner:stcct(所有者) /server:203.156.1.100(Ip地址) 删除用户的未迁入项: 输…

点击左侧跳到右侧

效果图 JS部分 function moveOption(e1, e2){ try{ for(var i0;i<e1.options.length;i ){ if(e1.options[i].selected){ var e e1.options[i]; e2.options.add(new Option(e.text, e.value)); e1.remove(i); iii-1 } } } catch(e){}} HTML以及CSS部分 <for…

IDC关于使用JBoss Fuse的商业价值的报告(与Apache Camel一起使用)

这只是一篇博客文章&#xff0c;具有更多的商业性质&#xff0c;但是您不能一无所有。 实际上&#xff0c;这也是使Apache Camel保持活力并保持良好状态的原因&#xff0c;这还归功于其商业上的成功。 希望从JBoss Fuse之类的产品中寻找有关在商业上使用Apache Camel的附加值的…

Spring-Quartz (一)

摘自&#xff1a; http://www.blogjava.net/Jay2009/archive/2009/03/25/259176.htmlSpring为创建Quartz的Scheduler、Trigger和JobDetail提供了便利的FactoryBean类&#xff0c;以便能够在Spring 容器中享受注入的好处。此外Spring还提供了一些便利工具类直接将Spring中的Bean…

在Java EE 7上骑骆驼–带有Swagger文档的REST服务

骆驼开箱即用。 Swagger集成就是其中之一。 不幸的是&#xff0c;大多数已经存在的功能都严重依赖于Spring。 但这并不能阻止我们在普通的Java EE 7应用程序中使用它们&#xff0c;因为有时它只是服务器的轻量级变体。 但我不想再对此进行讨论。 相反&#xff0c;我认为在所有情…

怎么隐藏滚动条又能滚动

1 <!DOCTYPE html>2 <html lang"en">3 <head>4 <meta charset"UTF-8">5 <title>滚动条隐藏</title>6 <style>7 body, ul, li {8 margin: 0;9 padding: 0; 10 …

Eclipse to android

JDK Eclipse Android SDK ADT 1 必须软件 Java JDK SE 1.6 (jdk-7u9-windows-i586.exe) Eclipse (Eclipse IDE for Java Developers) Google Android SDK (android-sdk_r15-windows.zip) ADT (ADT-15.0.0.zip) 如果找不到可参考&#xff1a; http://blog.csdn.net/zhenyong…

canvas画饼图

<style> body { background: black; text-align: center; } #cans { background: white; } </style> <script> function disToRad(n){//将度数表示弧度计算的方法 return n*Math.PI/180;//π用PI表示&#xff0c;π180&#xff0c;所以1PI/180 } w…

Web设计趋势分析

本文译自网站设计公司weavora.com&#xff0c;介绍了在他们眼里 8 个 Web 设计趋势&#xff1a;单页面、用照片做背景、色块设计、超大号的图片、聚焦简洁、响应式设计、视差滚动、强调字体&#xff0c;每个趋势后面都附了数个案例&#xff0c;相信对网站设计师会有一定的参考价…