局部变量写在循环内还是外

总览

有时会出现一个问题,即分配一个新的局部变量需要多少工作。 我的感觉一直是,代码已优化到成本为静态的程度,即一次执行,而不是每次运行都执行一次。

最近, Ishwor Gurung建议考虑将一些局部变量移出循环。 我怀疑这不会有所作为,但我从未测试过是否确实如此。

考试

这是我运行的测试:

public static void main(String... args) {for (int i = 0; i < 10; i++) {testInsideLoop();testOutsideLoop();}
}private static void testInsideLoop() {long start = System.nanoTime();int[] counters = new int[144];int runs = 200 * 1000;for (int i = 0; i < runs; i++) {int x = i % 12;int y = i / 12 % 12;int times = x * y;counters[times]++;}long time = System.nanoTime() - start;System.out.printf("Inside: Average loop time %.1f ns%n", (double) time / runs);
}private static void testOutsideLoop() {long start = System.nanoTime();int[] counters = new int[144];int runs = 200 * 1000, x, y, times;for (int i = 0; i < runs; i++) {x = i % 12;y = i / 12 % 12;times = x * y;counters[times]++;}long time = System.nanoTime() - start;System.out.printf("Outside: Average loop time %.1f ns%n", (double) time / runs);
}

输出以以下结尾:

内部 :平均循环时间3.6 ns
:平均循环时间3.6 ns
内部 :平均循环时间3.6 ns :平均循环时间3.6 ns

将测试时间增加到1亿次迭代,对结果的影响很小。

内部 :平均循环时间3.8 ns
:平均循环时间3.8 ns
内部 :平均循环时间3.8 ns :平均循环时间3.8 ns

>>, &, + I代替模和乘法

int x = i & 15;
int y = (i >> 4) & 15;
int times = x + y;

版画

内部 :平均循环时间1.2 ns
:平均循环时间1.2 ns
内部 :平均循环时间1.2 ns :平均循环时间1.2 ns

尽管模量相对昂贵,但测试的分辨率为0.1 ns或小于时钟周期的1/3。 这将显示两次测试之间的任何差异,以达到此准确性。

使用卡尺

正如@maaartinus所评论的那样, Caliper是一个微基准测试库,所以我对手工编写代码可能会慢得多感兴趣。

public static void main(String... args) {Runner.main(LoopBenchmark.class, args);
}public static class LoopBenchmark extends SimpleBenchmark {public void timeInsideLoop(int reps) {int[] counters = new int[144];for (int i = 0; i < reps; i++) {int x = i % 12;int y = i / 12 % 12;int times = x * y;counters[times]++;}}public void timeOutsideLoop(int reps) {int[] counters = new int[144];int x, y, times;for (int i = 0; i < reps; i++) {x = i % 12;y = i / 12 % 12;times = x * y;counters[times]++;}}
}

首先要注意的是,该代码较短,因为它不包括计时和印刷样板代码。 运行此程序,我将与第一个测试使用同一台计算机。

0% Scenario{vm=java, trial=0, benchmark=InsideLoop} 4.23 ns; σ=0.01 ns @ 3 trials
50% Scenario{vm=java, trial=0, benchmark=OutsideLoop} 4.23 ns; σ=0.01 ns @ 3 trialsbenchmark   ns linear runtime
InsideLoop 4.23 ==============================
OutsideLoop 4.23 =============================vm: java
trial: 0

用shift和and替换模数

0% Scenario{vm=java, trial=0, benchmark=InsideLoop} 1.27 ns; σ=0.01 ns @ 3 trials
50% Scenario{vm=java, trial=0, benchmark=OutsideLoop} 1.27 ns; σ=0.00 ns @ 3 trialsbenchmark   ns linear runtime
InsideLoop 1.27 =============================
OutsideLoop 1.27 ==============================vm: java
trial: 0

这与第一个结果一致,一次测试仅慢了0.4-0.6 ns。 (大约两个时钟周期),并且移位几乎没有差异,并且加上测试。 这可能是由于游标卡尺对数据进行采样而不会改变结果的缘故。

毫无疑问的是,当运行真实程序时,您获得的时间通常比微基准测试时间长,因为程序将执行更多操作,因此缓存和分支预测并不理想。 对所花费时间的一小部分过高估计可能更接近于您在实际程序中所看到的时间。

结论

这向我表明,在这种情况下,没有任何区别。 我仍然怀疑在JIT编译代码时分配局部变量的成本不会一次,并且没有考虑每个迭代的成本。

参考: 可以优化同步吗? 来自我们的JCG合作伙伴 Peter Lawrey,来自Vanilla Java博客。

翻译自: https://www.javacodegeeks.com/2012/12/local-variables-inside-a-loop-and-performance.html

局部变量写在循环内还是外

局部变量写在循环内还是外_循环内的局部变量和性能相关推荐

  1. stm32怎么调用for循环内部的变量_循环中的异步amp;amp;循环中的闭包

    在这之前先要了解一下 for循环中let 和var的区别 var 是函数级作用域或者全局作用域,let是块级作用域 看一个例子     function foo() {       for (var  ...

  2. java循环嵌套显示不全_循环嵌套问题

    循环嵌套问题 内部for循环 ,但外部for不循环 代码如下 : package test; import javax.servlet.*; import javax.servlet.http.*; ...

  3. 华兴数控g71外圆循环编程_G71外圆循环

    2006-04-10 什么时候用内循环?什么时候用外循环?有什么好处? 如果车外只是尘土的情况,例如行驶在土路上,应该紧闭车窗,开启室外循环,注意是要开室外循环.由于室外循环的过滤器完全可以滤掉沙土, ...

  4. R循环有两个_循环流化床锅炉富氧燃烧与CO2捕集发电机组运行能耗影响因素分析...

    发电过程中燃烧化石燃料产生的大量CO2排放是引起全球气候变化和一系列环境问题的主要原因,已经引起世界各国的广泛关注.通过富氧燃烧与CO2捕集技术对燃煤电厂排放的CO2进行大规模捕集,是减少温室气体排放 ...

  5. oracle内与外连接,Oracle (内连接)与(外连接)区别

    表stu id name 1, Jack 2, Tom 3, Kity 4, nono 表exam id grade 1, 56 2, 76 11, 89 内连接(显示两表匹配的id) select ...

  6. c++循环执行一个函数_循环

    循环 目标 程序的三大流程 while 循环基本使用 break 和 continue while 循环嵌套 01. 程序的三大流程 在程序开发中,一共有三种流程方式: 顺序 -- 从上向下,顺序执行 ...

  7. 单体内置对象_单体内置对象

    内置对象:由ECMAscript实现提供的,不依赖宿主环境的对象,这些对象再ES程序执行之前就已经存在 Global对象 Global全局对象是一个特别的对象(兜底对象) 不属于其他对象的属性和方法, ...

  8. 循环报数java代码_循环报数 Java实现

    输入1个数字和多个字符,中间均以空格隔开.假设数字取值为m(范围1~9),后面字符个数为n.假设n个字符围成一圈,从第一个字母开始循环报数,当数到m以后,第m个字母就出列,直到这n个字母全部出列.最后 ...

  9. java循环练习题及答案_循环练习题及答案

    Java循环练习题及答案 1,任意输入一个整数(小于10位),求它的位数 import java.util.Scanner; public class BitNum { } public static ...

最新文章

  1. 放大缩小html文字,jquery放大缩小文字
  2. oracle中的listener.ora和tnsnames.ora
  3. 福州大学软件工程1816 | W班 第7次作业成绩排名
  4. Linux系统下Configure命令参数解释说明
  5. css3加载中动画效果,CSS3实现加载中的动画效果
  6. PHP error_reporting() 函数
  7. Python嗅探socket
  8. mysql汉字格式_mysql 中的varchar255 uft-8 的格式到底能放多少汉字
  9. 深度学习论文TOP10,2019一季度研究进展大盘点
  10. 马斯克召集百名员工测试完全自动驾驶,1.3万美元大优惠!先到先得
  11. 杰控连接mysql_工控自动化应用方案:杰控FameView组态软件在数据库连接和查询方面的应用...
  12. 西门子plc编程软件step 7 microwin smart下载指南
  13. DWG文件损坏了怎么办?
  14. 洛谷-3803 【模板】多项式乘法(FFT,NNT)
  15. Win10安装-我们无法创建新的分区,也找不到现有的分区
  16. 项目经理如何处理中途接手的项目
  17. 尘封多年的期权,价值千万...
  18. java实现图片上传至本地
  19. 添加飞船图像:创建ship类与在屏幕上绘制飞船
  20. VELO3D将推出1米高的大型工业3D金属打印机,Knust-Godwin成为首家客户

热门文章

  1. 面试时如何介绍自己的项目经验
  2. 分布式一致性算法:可能比你想象得更复杂
  3. java嵌套类与内部类
  4. 计划得一步一步实施,题库首先是第一步!
  5. layui结合springboot上传图片
  6. javaSE视频教程正式启动
  7. struts基本概念(2)
  8. MVC自动配置原理---SpringBoot
  9. C++比较两个字符串是否完全相同
  10. (转)linux上nginx源码编译安装