我们都去过那儿。 在查看设计不良的代码的同时,听听作者对人们永远不应该牺牲性能而不是设计的解释。 而且,您不能说服作者摆脱其500行方法,因为链接方法调用会破坏性能。

好吧,这可能在1996年左右是正确的。 但是自那时以来, JVM已经发展成为一款了不起的软件。 找出它的一种方法是开始更深入地研究虚拟机执行的优化。 JVM应用的技术库非常广泛,但是让我们更详细地研究其中一种。 即方法内联 。 通过以下示例最容易解释:

int sum(int a, int b, int c, int d) {return sum(sum(a, b),sum(c, d));
}int sum(int a, int b) {return a + b;
}

当运行此代码时, JVM将弄清楚它可以用更有效的所谓“内联”代码代替:

int sum(int a, int b, int c, int d) {return a + b + c + d;
}

您必须注意,此优化是由虚拟机而不是由编译器完成的。 最初做出此决定的原因并不透明。 毕竟-如果您查看上面的示例代码-为什么在编译时可以推迟优化以产生更有效的字节码? 但是,考虑到其他不太明显的情况,JVM是执行优化的最佳位置:

  • JVM除了静态分析外还配备了运行时数据。 在运行时,JVM可以根据最常执行的方法,冗余的负载,何时安全使用副本传播等做出更好的决策。
  • JVM已获得有关基础体系结构的信息-内核数,堆大小和配置,因此可以根据此信息进行最佳选择。

但是,让我们在实践中看到这些假设。 我创建了一个小型测试应用程序 ,它使用几种不同的方法将1024个整数加在一起。

  • 相对合理的一种,其中实现只是对包含1024个整数的数组进行迭代,并将结果求和。 InlineSummarizer.java中提供了此实现。
  • 基于递归的分而治之方法。 我采用原始的1024个元素数组,然后将其递归地分成两半,因此第一个递归深度为我提供了两个512个元素数组,第二个深度为4个256个元素数组,依此类推。 为了将所有1024个元素加在一起,我引入了1023个其他方法调用。 此实现作为RecursiveSummarizer.java附加。
  • 天真的分而治之的方法。 这也划分了原始的1024个元素的数组,但是通过在分开的两半上调用其他实例方法-即我嵌套了sum512(),sum256(),sum128(),…,sum2()调用,直到我总结了所有元素。 与递归一样,我在源代码中介绍了1023个其他方法调用。

我有一个测试班来运行所有这些示例。 最初的结果来自未优化的代码:

从上面可以看出,内联代码是最快的。 而我们引入了1023个其他方法调用的方法则要慢25,000ns。 但是此图像必须加以警告-它是JIT尚未完全优化代码的运行快照。 在我2010年中期的MB Pro中,根据实施情况,运行了200到3000次。

更现实的结果如下。 我已经运行了所有汇总器实现超过1,000,000次,并丢弃了JIT尚未成功实现魔术效果的运行。

我们可以看到,即使内联代码仍然表现最佳,但迭代方法也以相当快的速度飞速发展。 但是递归明显不同–当迭代方法仅以20%的开销关闭时,RecursiveSummarizer会花费内联代码需要完成的340%的时间。 显然,这是应该注意的事情–使用递归时,JVM是无助的,无法内联方法调用。 因此,在使用递归时请注意此限制。

除了递归-方法开销几乎不存在。 源代码中有1023个其他方法调用之间的时间差仅为205 ns。 请记住,那是我们用于测量的那纳秒(10 ^ -9 s)。 因此,借助JIT,我们可以安全地忽略方法调用带来的大部分开销。 下次当您的同事将笨拙的设计决策隐藏在通过调用堆栈弹出效率不高的语句后面时,请让他首先完成一个小的JIT崩溃过程 。 如果您希望有能力阻止他将来的荒唐言论,请订阅我们的RSS或Twitter提要,我们很高兴为您提供未来的案例研究。

全面披露:本文所用测试用例的灵感来自Tomasz Nurkiewicz 博客文章 。

参考: Plumbr Blog博客上的JCG合作伙伴 Nikita Salnikov Tarnovski 用Java进行方法调用的成本是多少 ?

翻译自: https://www.javacodegeeks.com/2013/02/how-expensive-is-a-method-call-in-java.html

Java中的方法调用有多昂贵相关推荐

  1. java调用怎么调用方法区_Java中的方法调用有多昂贵

    java调用怎么调用方法区 我们都去过那儿. 在查看设计不良的代码的同时,听听作者对人们永远不应该牺牲性能而不是设计的解释. 而且,您不能说服作者摆脱其500行方法,因为链接方法调用会破坏性能. 好吧 ...

  2. java 调用 js性能_太快了,太变态了:什么会影响Java中的方法调用性能?

    java 调用 js性能 那么这是怎么回事? 让我们从一个简短的故事开始. 几周前,我提议对Java核心libs邮件列表进行更改 ,以覆盖当前final一些方法. 这刺激了一些讨论主题-其中之一是其中 ...

  3. 太快了,太变态了:什么会影响Java中的方法调用性能?

    那么这是怎么回事? 让我们从一个简短的故事开始. 几周前,我提议对Java核心libs邮件列表进行更改 ,以覆盖当前final一些方法. 这刺激了一些讨论主题-其中之一是其中一个性能回归通过采取这是一 ...

  4. JAVA中native方法调用C语言实现学习

    在java虚拟机规范的内存管理划分中,对于虚拟机内存空间划分中专门划了一块内存叫做"本地方法栈(Native Method Stack)".本地方法栈是为了java专门用来调用na ...

  5. java中的输入语句判断正负_在java中使用方法调用统计数组中正数的个数,将判断数据的正负功能定义成方法...

    满意答案 donglin820 推荐于 2018.04.21 public class TestDemo { static int count = 0;// 统计整数的个数 public static ...

  6. 使用JavaSymbolSolver解决Java代码中的方法调用

    为什么创建java-symbol-solver? 几年前,我开始使用JavaParser ,然后开始做出贡献. 不久之后,我意识到我们想对Java代码执行的许多操作不能仅通过使用解析器生成的抽象语法树 ...

  7. eclipse折叠if语句块_「03」java中的方法以及控制语句

    语句块(有时叫做复合语句),是用花括号扩起的任意数量的简单Java语句.块确定了局部变量的作用域.块中的程序代码,作为一个整体,是要被一起执行的.块可以被嵌套在另一个块中,但是不能在两个嵌套的块内声明 ...

  8. java中clone方法_Java Object clone()方法– Java中的克隆

    java中clone方法 Cloning is the process of creating a copy of an Object. Java Object class comes with na ...

  9. java 返回值判断_在Java中判断方法重载的条件除了参数外,还可以通过返回值类型判断。_学小易找答案...

    [单选题]若int x;且有下面的程序片断,则输出结果是() . for (x=3; x<6; x++) { printf((x%2) ? "##%d" : "** ...

最新文章

  1. mysql查询赋值、修改拼接字符串
  2. 复杂性系统面临的难题
  3. js中匿名函数的N种写法
  4. WCF的CommunicationObjectFaultedException异常问题
  5. 异构网络垂直切换算法lte/wimax
  6. 不同版本GCC编译器之间的切换
  7. Python 数据分析与展示笔记2 -- 图像手绘效果
  8. go日期和时间相关函数使用示例
  9. c语言判断化学方程式,下列是某同学写的六个化学方程式:①Mg+O2点燃.MgO2②C+O2点燃.CO...
  10. 高考封路,大叔骑车强闯
  11. Bailian2696 计算表达式的值【入门】
  12. 安卓手机投射电脑屏幕 手机投屏电脑
  13. 【矩阵论笔记】Schmidt正交化、标准正交基
  14. 供应链管理的三个层次
  15. 餐馆点菜系统python程序_Python写一个自动点餐程序
  16. JavaScript排他思想
  17. 如何判断一个多边形的环是逆时针还是顺时针
  18. win10修改用户名导致问题及解决
  19. 计算机组成原理学习之路(一)——数据表示
  20. (转)blackrock的阿拉丁系统与风险管理

热门文章

  1. 设计费收费标准2002修订_@设计师,2019景观园林设计收费标准,注意查收!
  2. springboot接收浏览器发送delete请求( method not allowed 405解决方法)
  3. spring(11)使用对象-关系映射持久化数据
  4. 单列集合List的实现类
  5. apache ignite_Kubernetes集群上的Apache Ignite和Spring第3部分:测试应用程序
  6. spring-junit4_基于Spring的应用程序-迁移到Junit 5
  7. aws sqs_在Spring使用AWS SQS创建消息驱动Bean
  8. spring bean依赖_Spring @Configuration并将bean依赖项作为方法参数注入
  9. Java的Kafka:构建安全,可扩展的消息传递应用程序
  10. Spring@主要注释