温州网站开发流程,汕头在线制作网站,做微信商城网站,建设网站如入什么费我们都去过那儿。 在查看设计不良的代码的同时#xff0c;听听作者对人们永远不应该牺牲性能而不是设计的解释。 而且#xff0c;您不能说服作者摆脱其500行方法#xff0c;因为链接方法调用会破坏性能。 好吧#xff0c;这可能在1996年左右是正确的。 但是自那时以来听听作者对人们永远不应该牺牲性能而不是设计的解释。 而且您不能说服作者摆脱其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个元素的数组但是通过在分开的两半上调用其他实例方法-即我嵌套了sum512sum256sum128…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