怎样做自己的个人网站,苏州网络网站建设,自助手机网站建站软件,网站开发所有工具多大在此JAX Magazine的预览预览中#xff0c;JAX伦敦发言人Angelika Langer为使用Java流的任何人回答了最重要的问题#xff1a;它们真的更快吗#xff1f; Java 8是JDK收集框架的主要新增功能#xff0c;即流API。 与集合相似#xff0c;流表示元素序列。 集合支持对单个元… 在此JAX Magazine的预览预览中JAX伦敦发言人Angelika Langer为使用Java流的任何人回答了最重要的问题它们真的更快吗 Java 8是JDK收集框架的主要新增功能即流API。 与集合相似流表示元素序列。 集合支持对单个元素起作用的操作例如add() remove()和contains() 。 相反流具有批量操作例如forEach() filter() map()和reduce() 它们访问序列中的所有元素。 Java流的概念受功能编程语言的启发其中相应的抽象通常称为序列该序列也具有filter-map-reduce操作。 由于这种相似性Java 8至少在某种程度上除了其一直支持的面向对象范例之外还允许一种函数式编程样式。 也许与普遍的看法相反Java编程语言的设计人员没有扩展Java及其JDK来允许Java中的功能编程也没有将Java变成“目标与功能”混合编程语言。 发明Java流的真正动机是性能或者更确切地说是使并行性更易于软件开发人员访问请参见Lambda州的Brian Goetz 。 考虑到硬件的发展方式这个目标对我来说很有意义。 我们的硬件今天有数十个cpu内核将来可能还会有数百个。 为了有效利用硬件功能从而达到最新的执行性能我们必须并行化。 毕竟–在多核平台上运行单个线程有什么意义 同时多线程编程被认为是困难且容易出错的这是正确的。 流有两种形式顺序流和并行流旨在隐藏运行多个线程的复杂性。 并行流使魔术般轻松地并且以每个Java开发人员都可以访问的方式并行执行批量操作变得极为容易。 并行流操作是否比顺序操作快 听到Angelika Langer在2015年JAX伦敦上的演讲。 因此我们来谈谈性能。 Java 8流有多快 一个普遍的期望是流操作的并行执行比仅单个线程的顺序执行要快。 是真的吗 流会提高性能吗 为了回答有关性能的问题我们必须进行衡量即运行一个微基准测试。 标杆管理也很困难且容易出错。 您需要执行适当的预热注意各种失真的影响从虚拟机的JIT编译器应用的优化消除臭名昭著的死代码到硬件优化例如如果增加一个内核的cpu频率则应注意其他核心处于闲置状态。 通常必须以一粒盐作为基准结果。 每个基准都是实验。 其结果取决于上下文。 永远不要相信在硬件环境中尚未产生的基准数据。 这样说让我们尝试一下。 将流与循环进行比较 首先我们想了解流的批量操作与常规的传统for-比较。 首先出于性能考虑是否值得使用流 我们将用于基准测试的序列是一个int-数组其中填充了500,000个随机整数值。 在此数组中我们将搜索最大值。 这是带有for-循环的传统解决方案 int[] a ints;
int e ints.length;
int m Integer.MIN_VALUE;
for(int i0; i e; i) if(a[i] m) m a[i]; 这是使用顺序IntStream的解决方案 int m Arrays.stream(ints).reduce(Integer.MIN_VALUE, Math::max); 我们在具有适当预热功能的过时硬件双核无动态超频上进行了测量并得出了中途可靠的基准数据。 这是在特定情况下的结果 int-array, for-loop : 0.36 ms
int-array, seq. stream: 5.35 ms 结果令人震惊旧的for-循环比顺序流快15倍。 真令人失望 多年的开发工作花费在为Java 8构建流上然后进行此 可是等等 在得出流非常慢的结论之前让我们看看如果用ArrayList Integer替换int- array会发生什么。 这是for-循环 int m Integer.MIN_VALUE;
for (int i : myList)if (im) mi; 这是基于流的解决方案 int m myList.stream().reduce(Integer.MIN_VALUE, Math::max); 结果如下 ArrayList, for-loop : 6.55 ms
ArrayList, seq. stream: 8.33 ms 同样 for-循环比顺序流操作要快但是ArrayList上的差异不如在阵列上那么重要。 让我们考虑一下。 为什么结果相差这么大 有几个方面需要考虑。 首先访问数组元素非常快。 这是基于索引的内存访问没有任何开销。 换句话说这是简单的底层存储访问。 另一方面通过迭代器访问集合中的元素例如ArrayList并且迭代器不可避免地增加了开销。 另外对集合元素进行装箱和拆箱会产生开销而int数组则使用普通原始类型int。 本质上对于该ArrayList测量通过迭代和拳击开销而对于INT-阵列附图示出的优点是支配for-环路。 其次我们是否曾认真地期望过流会比普通的for-loop更快 编译器在优化循环方面拥有40多年的经验虚拟机的JIT编译器尤其易于以与我们的基准测试相同的步伐来优化阵列上的for-循环。 另一方面流是Java的最新添加并且JIT编译器尚未尚未对其执行任何特别复杂的优化。 第三我们必须记住一旦掌握了序列元素我们就不会做太多事情。 我们花了很多精力来尝试访问元素然后对它进行的工作并不多。 我们只比较两个整数在JIT编译后它们几乎不止一个汇编指令。 因此我们的基准测试说明了元素访问的成本–不一定是典型情况。 如果应用于序列中每个元素的功能是CPU密集型的则性能指标将发生重大变化。 您会发现如果功能受CPU的限制很大则for循环流和顺序流之间将不再有可测量的差异。 加入我们的JAX伦敦-Java和软件创新者大会。 使用以下代码可享受10的折扣MP_JCG10 从该基准实验得出的最终结论并非并非流总是比循环慢。 是的流有时比循环慢但它们也可以同样快。 这要视情况而定。 带回家的要点是顺序流不会比循环快。 如果使用顺序流则出于性能原因请不要这样做 之所以这样做是因为您喜欢函数式编程风格。 那么性能改进流是在哪里发明的呢 到目前为止我们仅将循环与流进行了比较。 并行化如何 流的点是易于并行化以实现更好的性能。 比较顺序流与并行流 作为第二个实验我们想弄清楚顺序流与并行流在性能方面的比较。 并行流操作是否比顺序操作快 我们使用填充500,000个整数值的同一int-数组。 这是顺序流操作 int m Arrays.stream(ints).reduce(Integer.MIN_VALUE, Math::max); 这是并行流操作 int m Arrays.stream(ints).parallel().reduce(Integer.MIN_VALUE, Math::max); 我们的期望是并行执行应该比顺序执行更快。 由于测量是在双核平台上进行的因此并行执行最多可以是顺序执行的两倍。 理想情况下顺序/并行性能之比应为2.0。自然地并行执行确实会引入一些开销用于拆分问题创建子任务在多个线程中运行子任务收集其部分结果以及产生总体结果。 该比率将小于2.0但应该接近。 这些是实际的基准测试结果 sequential parallel seq./par.
int-array 5.35 ms 3.35 ms 1.60 通过我们的基准进行的现实检查得出的比率顺序/并行仅为1.6而不是2.0这说明了并行执行涉及的开销量以及在此特定平台上如何好坏得到超额补偿。 您可能会倾向于概括这些数字并得出结论并行流始终比顺序流快也许不如人们希望的那样快在双核硬件上但是至少更快。 但是事实并非如此。 同样有许多方面有助于并行流操作的性能。 其中之一是流源的可拆分性。 数组可以很好地拆分 只需进行索引计算就可以找出中间元素并将数组拆分为两半。 没有开销因此几乎没有拆分成本。 与数组相比集合拆分的难易程度如何 拆分二叉树或链表需要什么 在某些情况下对于不同类型的集合您将观察到截然不同的性能结果。 另一个方面是有状态性。 一些流操作保持状态。 一个示例是distinct()操作。 这是一个中间操作可消除输入序列中的重复项即它返回具有不同元素的输出序列。 为了确定下一个元素是否重复操作必须与它已经遇到的所有元素进行比较。 为此它维护某种数据结构作为其状态。 如果在并行流上调用distinct() 则其状态将被多个工作线程并发访问这需要某种形式的协调或同步这会增加开销从而减慢并行执行的速度最大程度地降低了并行执行的程度。比顺序执行慢。 考虑到这一点可以公平地说流的性能模型并非微不足道。 幼稚地期望并行流操作总是比顺序流操作快。 性能提升如果有的话取决于许多因素我在上文中简要提到了其中的一些因素。 如果您熟悉流的内部工作原理则可以对并行流操作的性能做出明智的猜测。 但是您需要进行大量基准测试以便针对给定的上下文确定并行进行是否值得。 实际上在某些情况下并行执行要比顺序执行慢并且在所有情况下盲目使用并行流可能会适得其反。 实现是是的并行流操作易于使用并且通常比顺序操作运行得更快但是不要指望奇迹。 另外不要猜测 相反要进行很多基准测试。 这是《 JAX杂志》的先睹为快–在此处注册以获取更多免费的开发人员提示趋势和教程。 翻译自: https://www.javacodegeeks.com/2015/07/java-performance-tutorial-how-fast-are-the-java-8-streams.html