流绩效–您的想法

上周,我介绍了一些有关Java 8流性能的基准测试结果。 你们和gal足够感兴趣,可以留下一些想法,还有哪些可以介绍。

这就是我所做的,这是结果。

总览

最后一篇文章的序言也适用于此。 阅读它,以找出所有数字为何撒谎,我如何提出这些数字以及如何复制它们。

我在GitHub上的代码中添加了一个新类CommentOperationsBenchmark ,其中包括本文中讨论的基准。 我还更新了Google电子表格,以包括新的数字。

比较的影响

真好 长期以来一直在说将Java写成Ansi C更快(数组而不是列表)。

兔子洞的下一步是…

尝试{for(int i = 0 ;;)做东西; } catch(ex ex ex){等等! }

根本不检查循环,仅捕获异常,非常适合高清像素处理。

混沌实验室

WAT? 人们正在这样做吗?

打破ArrayIndexOotOfBoundsException

public int array_max_forWithException() {int m = Integer.MIN_VALUE;try {for (int i = 0; ; i++)if (intArray[i] > m)m = intArray[i];} catch (ArrayIndexOutOfBoundsException ex) {return m;}
}

也许他们应该停下来,因为它看起来并不能改善性能:

以毫秒为单位的运行时间标准化为1'000'000个元素
5万 500'000 1'000'000 5'000'000 10'000'000 50'000'000
array_max_for 0.261 0.261 0.277 0.362 0.347 0.380
array_max_forWithException 0.265 0.265 0.273 0.358 0.347 0.386


看来,用于打破循环的机制没有可衡量的影响。 这是有道理的,因为循环展开可以避免大多数比较,并且引发异常的代价在几微秒的范围内 ,因此比此处发生的情况小几个数量级。

这是假设编译器确实有更多技巧。 也许它更深刻地理解了循环,并且JIT将这两种方法编译为相同的指令。

附带说明一下:看看循环后array_max_forWithException如何没有return语句?

事实证明Java编译器可以识别简单的无限循环 。 哇! 因此,它知道具有有限计算的每个代码路径都会返回,而不关心无限的代码路径。

归结为以下内容:

一无所有

public int infiniteLoop() {for(;;);
}

您永不停止学习……

作业的影响

[F]或“最大”测试我希望每次迭代更新局部变量都会有一些阻力。 我很好奇寻找最小值是否在可比较的时间内运行。

b0b0b0b

这是指所有测试都是在数组或列表上运行的,这些数组或列表的元素等于结构中的索引,即[0,1,2,…,n-1]。 因此,找到最大值确实需要n个分配。

那找到一个只需要一个作业的最小值呢?

以毫秒为单位的运行时间标准化为1'000'000个元素
5万 500'000 1'000'000 5'000'000 10'000'000 50'000'000
array_max_for 0.261 0.261 0.277 0.362 0.347 0.380
array_min_for 0.264 0.260 0.280 0.353 0.348 0.359


不,没有区别。 我的猜测是,由于流水线作业,分配实际上是免费的。

由Khalid Albaih在CC-BY 2.0下发布–我改变了视野。

由Khalid Albaih在CC-BY 2.0下发布 –我改变了视野。

拳击的影响

关于拳击有两条评论。

最好看到Integer []实现,以确认对拳击的怀疑。

黏黏的

好吧,让我们这样做。 以下数字显示了int [],Integer []和List <Integer>上的for循环和for-each循环:

以毫秒为单位的运行时间标准化为1'000'000个元素
5万 500'000 1'000'000 5'000'000 10'000'000 50'000'000
array_max_for 0.261 0.261 0.277 0.362 0.347 0.380
array_max_forEach 0.269 0.262 0.271 0.349 0.349 0.356
boxedArray_max_for 0.804 1.180 1.355 1.387 1.306 1.476
boxedArray_max_forEach 0.805 1.195 1.338 1.405 1.292 1.421
list_max_for 0.921 1.306 1.436 1.644 1.509 1.604
list_max_forEach 1.042 1.472 1.579 1.704 1.561 1.629


我们可以清楚地看到,运行时的主要指标是数据结构是包含基元还是对象。 但是将Integer数组包装到列表中会导致额外的速度降低。

Yann Le Tallec也对拳击发表了评论:

intList.stream()。max(Math :: max); 造成不必要的拆箱。
intList.stream()。mapToInt(x-> x).max(); 速度大约是阵列版本的两倍。

扬·勒·塔雷克(Yann Le Tallec)

此声明与我们在上一篇文章中得出的结论一致:尽快对流取消装箱可能会提高性能。

只是再次检查:

以毫秒为单位的运行时间标准化为1'000'000个元素(以%为单位的错误)
5万 500'000 1'000'000 5'000'000 10'000'000 50'000'000
boxedArray_max _stream 4.231(43%) 5.715(3%) 5.004(27%) 5.461(53%) 5.307(56%) 5.507(54%)
boxedArray_max _stream_unbox 3.367(<1%) 3.515(<1%) 3.548(2%) 3.632(1%) 3.547(1%) 3.600(2%)
list_max _stream 7.230(7%) 6.492(<1%) 5.595(36%) 5.619(48%) 5.852(45%) 5.631(51%)
list_max _stream_unbox 3.370(<1%) 3.515(1%) 3.527(<1%) 3.668(3%) 3.807(2%) 3.702(5%)


这似乎证实了这一说法。 但是结果看起来非常可疑,因为错误很大。 使用不同的设置反复运行这些基准测试显示了一种模式:

  • 存在两种性能水平,一种是〜3.8 ns / op,一种是〜7.5 ns / op。
  • 未装箱的流只表现更好。
  • 盒装流的单个迭代通常在这两个级别中的任何一个上运行,但很少在另一个时间运行。
  • 大多数情况下,行为只会在分支之间变化(即从一组迭代到下一组)。

这一切都令人怀疑我的测试设置存在问题。 听到任何想法的人,我会很有趣。

更新资料

Yann确实有一个主意,并指出了这个有趣的问题和有关StackOverflow的出色答案 。 现在,我最好的猜测是,装箱的流可以在未装箱的水平上运行,但可能会因意外的非优化而祈祷。

硬件的影响

Redditor robi2106在其“ i5-4310 @ 2Ghz w 8GB DDR2”上运行了500'000个元素的套件。 我将结果添加到电子表格中 。

很难从数据中得出结论。 Robi指出“在这2.5个小时中我也没有停止使用我的系统”,这也许可以解释巨大的误差范围。 他们的平均年龄是我的23倍,平均是我的168倍。 (另一方面,我也继续使用我的系统,但是负载很低。)

如果斜视一下,可以推断出i5-4310在简单的计算上会稍快一些,但在更复杂的计算上会落后一些。 考虑到i7-4800的内核数量是原来的两倍,通常可以达到并行性能。

语言的影响

这与Scala(带有@specialized)相比,会很有趣。

加密货币6

我仍然没有尝试使用Scala,也不想为一个基准测试而努力。 也许经验更丰富或更鲜美的人可以尝试一下?

反射

在解释这些数字时,请记住,这些迭代执行了非常便宜的操作。 上次我们发现已经很简单的算术运算会导致足够的CPU负载, 几乎完全抵消了迭代机制的差异 。 因此,像往常一样,不要过早优化!

总而言之,我会说:没有新发现。 但是,我很喜欢与您讨论您的想法,如果您有更多想法,请发表评论。 甚至更好的是,自己尝试一下并发布结果。

翻译自: https://www.javacodegeeks.com/2015/09/stream-performance-your-ideas.html

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

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

相关文章

java中JVM的原理

一、java虚拟机的生命周期&#xff1a; Java虚拟机的生命周期 一个运行中的Java虚拟机有着一个清晰的任务&#xff1a;执行Java程序。程序开始执行时他才运行&#xff0c;程序结束时他就停止。你在同一台机器上运行三个程序&#xff0c;就会有 三个运行中的Java虚拟机。 Java虚…

2022将至,前端程序员们应该一起放个烟花庆祝一下,走起

前言&#xff1a;小时候&#xff0c;在我印象中&#xff0c;每到快过年的时候就有很多卖炮仗的&#xff0c;一般也就是阳历的12月份到明年的正月15号卖炮仗的商家比较多&#xff0c;省下买辣条的钱去买炮仗&#xff0c;在老家也就过年和除夕两天及正月15日这几天放烟花和炮仗比…

微信红包封面开放平台序列号

微信红包封面开放平台是一款可以领取微信红包封面的平台&#xff0c;最近网上非常流行好玩的微信红包封面&#xff0c;每一种封面都极具特色&#xff0c;让你的微信红包与众不同&#xff0c;还可以定制专属的微信红包封面&#xff0c;不过名额有限&#xff0c;这边为大家带来这…

ios多线程 -- NSOperation 简介

NSOperation的作⽤&#xff1a;配合使用NSOperation和NSOperationQueue也能实现多线程编程 NSOperation和NSOperationQueue实现多线程的具体步骤&#xff1a; 1&#xff09;先将需要执行的操作封装到一个NSOperation对象中 2&#xff09;然后将NSOperation对象添加到NSOpera…

在没有复杂插件的情况下从Eclipse启动和调试Tomcat

像Eclipse这样的现代IDE提供了各种插件来简化Web开发。 但是&#xff0c;我相信将Tomcat作为“常规” Java应用程序启动仍然可以提供最佳的调试体验。 大多数时候&#xff0c;这是因为这些工具将Tomcat或任何其他servlet容器作为外部进程启动&#xff0c;然后在其上附加一个远程…

【javascript高级教程】JavaScript 对象

JavaScript 中的所有事物都是对象&#xff1a;字符串、数值、数组、函数...及自定义对象 JavaScript 提供多个内建对象&#xff0c;比如 String、Date、Array 等等。 对象只是带有属性和方法的特殊数据类型。 布尔型可以是一个对象。数字型可以是一个对象。字符串也可以是一个…

php 字符串函数

函数名描述实例输入输出trim()删除字符串两端的空格和其他预定义字符 $str"\r\nHello\r\n"; echo trim($str) 目标字符串 清除后的字符串 rtrim()/chop() 删除字符串右边的空格或其他预定义字符 ltrim() 删除字符串左边的空格或其他预定义字符 …

Lucene分析过程指南

本文是我们名为“ Apache Lucene基础知识 ”的学院课程的一部分。 在本课程中&#xff0c;您将了解Lucene。 您将了解为什么这样的库很重要&#xff0c;然后了解Lucene中搜索的工作方式。 此外&#xff0c;您将学习如何将Lucene Search集成到您自己的应用程序中&#xff0c;以…

【JavaScript高级教程】JavaScript prototype(原型对象)

所有的 JavaScript 对象都会从一个 prototype&#xff08;原型对象&#xff09;中继承属性和方法。 function Person(first, last, age, eyecolor) {this.firstName first;this.lastName last;this.age age;this.eyeColor eyecolor; }var myFather new Person("John…

【javascript高级教程】JavaScript Number 对象

JavaScript 只有一种数字类型。可以使用也可以不使用小数点来书写数字。 var pi3.14; // 使用小数点 var x34; // 不使用小数点 极大或极小的数字可通过科学&#xff08;指数&#xff09;计数法来写&#xff1a; var y123e5; // 12300000 var z123e-5; // 0.0…

【leetcode】clone-graph

写在前面的话&#xff1a; 看了看自己的博客&#xff0c;从一月底开始就没怎么更新过&#xff0c;我也确实将近5个月没怎么写代码了。今天突然觉得有些心慌&#xff0c;感觉手都已经生疏了。果然&#xff0c;随便找了道题就卡住了。隐约感觉要用map但又不太记得用法了&#xff…

【javascript高级教程】JavaScript 字符串(String) 对象

String 对象用于处理已有的字符块。 JavaScript 字符串 一个字符串用于存储一系列字符就像 "John Doe". 一个字符串可以使用单引号或双引号&#xff1a; var carname"Volvo XC60"; var carnameVolvo XC60; 你使用位置&#xff08;索引&#xff09;可以…

Redis教程:NoSQL键值存储

课程大纲 Redis是使用ANSI C编写的具有可选持久性的开源&#xff0c;网络化&#xff0c;内存中键值数据存储。根据DB-Engines.com的月度排名&#xff0c;Redis是最受欢迎的键值存储。 它的名字意思是远程字典服务器。 Redis已获得BSD许可&#xff0c;并且通常被称为数据结构服…

java 里面eaquls和==区别

java中的数据类型&#xff0c;可分为两类&#xff1a; 1.基本数据类型&#xff0c;也称原始数据类型。byte,short,char,int,long,float,double,boolean 他们之间的比较&#xff0c;应用双等号&#xff08;&#xff09;,比较的是他们的值。 2.复合数据类型(类) 当他们用…

【javascript高级教程】JavaScript Array(数组) 对象

数组对象的作用是&#xff1a;使用单独的变量名来存储一系列的值。 创建数组, 为其赋值&#xff1a; var mycars new Array(); mycars[0] "Saab"; mycars[1] "Volvo"; mycars[2] "BMW"; 什么是数组? 数组对象是使用单独的变量名来存储一…

Chrome 开发工具之Network

经常会听到比如"为什么我的js代码没执行啊&#xff1f;","我明明发送了请求&#xff0c;为什么反应&#xff1f;","我这个网站怎么加载的这么慢&#xff1f;"这类的问题&#xff0c;那么问题既然存在&#xff0c;就需要去解决它&#xff0c;需要…

【javascript高级教程】JavaScript Date(日期) 对象

日期对象用于处理日期和时间。 创建日期 Date 对象用于处理日期和时间。 可以通过 new 关键词来定义 Date 对象。以下代码定义了名为 myDate 的 Date 对象&#xff1a; 有四种方式初始化日期: new Date(); new Date(value); new Date(dateString); new Date(year, monthI…

实用常识_实用垃圾收集,第1部分–简介

实用常识这是我打算写的一系列博客文章的第一部分&#xff0c;其目的是解释垃圾回收在现实世界中如何工作&#xff08;尤其是在JVM中 &#xff09;。 我将介绍一些我认为对于充分理解垃圾收集对于实际目的是必需的理论&#xff0c;但是将其降至最低。 其动机是在各种情况下&…

重写AgileEAS.NET SOA 中间件平台账号密码的加密算法

一、平台简介 AgileEAS.NET SOA 中间件平台是一款基于基于敏捷并行开发思想和Microsoft .Net构件(组件)开发技术而构建的一个快速开发应用平台。用于帮助中小型软件企业建立一条适合市场快速变化的开发团队&#xff0c;以达到节省开发成本、缩短开发时间&#xff0c;快速适应市…

Java中的堆栈安全递归

在本文中&#xff0c;摘自《 Java中的函数式编程 》一书&#xff0c;我解释了如何使用递归&#xff0c;同时避免了StackOverflow异常的风险。 Corecursion正在使用第一步的输出作为下一步的输入来构成计算步骤。 递归是相同的操作&#xff0c;但是从最后一步开始。 在这种情况…