【Java】嵌套For循环性能优化案例
参考资料:http://cgs1999.iteye.com/blog/1596671
1 案例描述
某日,在JavaEye上看到一道面试题,题目是这样的:请对以下的代码进行优化
- for (int i = 0; i < 1000; i++)
- for (int j = 0; j < 100; j++)
- for (int k = 0; k < 10; k++)
- testFunction (i, j, k);
(注:为了同后面的内容一致,这里对原题目进行了部分修改)
2 案例分析
从给出的代码可知,不论如何优化,testFunction执行的次数都是相同的,该部分不存在优化的可能。那么,代码的优化只能从循环变量i、j、k的实例化、初始化、比较、自增等方面的耗时上进行分析。
首先,我们先分析原题代码循环变量在实例化、初始化、比较、自增等方面的耗时情况:
| 变量 | 实例化(次数) | 初始化(次数) | 比较(次数) | 自增(次数) |
| i | 1 | 1 | 1000 | 1000 |
| j | 1000 | 1000 | 1000 * 100 | 1000 * 100 |
| k | 1000 * 100 | 1000 * 100 | 1000 * 100 * 10 | 1000 * 100 * 10 |
(注:由于单次耗时视不同机器配置而不同,上表相关耗时采用处理的次数进行说明)
该代码的性能优化就是尽可能减少循环变量i、j、k的实例化、初始化、比较、自增的次数,同时,不能引进其它可能的运算耗时。
3 解决过程
从案例分析,对于原题代码,我们提出有两种优化方案:
3.1 优化方案一
代码如下:
- for (int i = 0; i < 10; i++)
- for (int j = 0; j < 100; j++)
- for (int k = 0; k < 1000; k++)
- testFunction (k, j, i);
该方案主要是将循环次数最少的放到外面,循环次数最多的放里面,这样可以最大程度的(注:3个不同次数的循环变量共有6种排列组合情况,此种组合为最优)减少相关循环变量的实例化次数、初始化次数、比较次数、自增次数,方案耗时情况如下:
| 变量 | 实例化(次数) | 初始化(次数) | 比较(次数) | 自增(次数) |
| i | 1 | 1 | 10 | 10 |
| j | 10 | 10 | 10 * 100 | 10 * 100 |
| k | 10 * 100 | 10 * 100 | 10 * 100 * 1000 | 10 * 100 * 1000 |
3.2 优化方案二
代码如下:
- int i, j, k;
- for (i = 0; i < 10; i++)
- for (j = 0; j < 100; j++)
- for (k = 0; k < 1000; k++)
- testFunction (k, j, i);
该方案在方案一的基础上,将循环变量的实例化放到循环外,这样可以进一步减少相关循环变量的实例化次数,方案耗时情况如下:
| 变量 | 实例化(次数) | 初始化(次数) | 比较(次数) | 自增(次数) |
| i | 1 | 1 | 10 | 10 |
| j | 1 | 10 | 10 * 100 | 10 * 100 |
| k | 1 | 10 * 100 | 10 * 100 * 1000 | 10 * 100 * 1000 |
4 解决结果
那么,提出的优化方案是否如我们分析的那样有了性能上的提升了呢?我们编写一些测试代码进行验证,数据更能说明我们的优化效果。
4.1 测试代码
- public static void testFunction(int i, int j, int k) {
- System.out.print(""); // 注:该方法不影响整体优化,这里只有简单输出
- }
- public static void testA() {
- long start = System.nanoTime();
- for (int i = 0; i < 1000; i++)
- for (int j = 0; j < 100; j++)
- for (int k = 0; k < 10; k++)
- testFunction(i, j, k);
- System.out.println("testA time>>" + (System.nanoTime() - start));
- }
- public static void testB() {
- long start = System.nanoTime();
- for (int i = 0; i < 10; i++)
- for (int j = 0; j < 100; j++)
- for (int k = 0; k < 1000; k++)
- testFunction(k, j, i);
- System.out.println("testB time>>" + (System.nanoTime() - start));
- }
- public static void testC() {
- long start = System.nanoTime();
- int i;
- int j;
- int k;
- for (i = 0; i < 10; i++)
- for (j = 0; j < 100; j++)
- for (k = 0; k < 1000; k++)
- testFunction(k, j, i);
- System.out.println("testC time>>" + (System.nanoTime() - start));
- }
4.2 测试结果
1、测试机器配置:Pentium(R) Dual-Core CPU E5400 @2.70GHz 2.70GHz, 2GB内存;
2、循环变量i、j、k循环次数分别为10、100、1000,进行5组测试,测试结果如下:
| 第1组 | 第2组 | 第3组 | 第4组 | 第5组 | |
| 原方案 | 171846271 | 173250166 | 173910870 | 173199875 | 173725328 |
| 方案一 | 168839312 | 168466660 | 168372616 | 168310190 | 168041251 |
| 方案二 | 168001838 | 169141906 | 168230655 | 169421766 | 168240748 |
从上面的测试结果来看,优化后的方案明显性能优于原方案,达到了优化的效果。但优化方案二并没有如我们预期的优于方案一,其中第2、4、5组的数据更是比方案一差,怀疑可能是循环次数太少,以及测试环境相关因素影响下出现的结果。
3、重新调整循环变量i、j、k循环次数分别为20、200、2000,进行5组测试,测试结果如下:
| 第1组 | 第2组 | 第3组 | 第4组 | 第5组 | |
| 原方案 | 1355397203 | 1358978176 | 1358128281 | 1350193682 | 1354786598 |
| 方案一 | 1343482704 | 1348410388 | 1343978037 | 1347919156 | 1340697793 |
| 方案二 | 1342427528 | 1343897887 | 1342662462 | 1342124048 | 1336266453 |
从上面的测试结果来看,优化后的方案基本符合我们的预期结果。
5 总结
从案例分析和解决过程中的三个表的分析可知,优化方案一和优化方案二的性能都比原代码的性能好,其中优化方案二的性能是最好的。在嵌套For循环中,将循环次数多的循环放在内侧,循环次数少的循环放在外侧,其性能会提高;减少循环变量的实例化,其性能也会提高。从测试数据可知,对于两种优化方案,如果在循环次数较少的情况下,其运行效果区别不大;但在循环次数较多的情况下,其效果就比较明显了。
6 参考资料
[1] http://www.javaeye.com/topic/762312
[2] http://www.javaeye.com/topic/632481
【Java】嵌套For循环性能优化案例的更多相关文章
- 嵌套For循环性能优化案例
转自:http://cgs1999.iteye.com/blog/1596671 涨知识~~~ 1 案例描述 某日,在JavaEye上看到一道面试题,题目是这样的:请对以下的代码进行优化 for (i ...
- 嵌套For循环性能优化
请对以下的代码进行优化 for (int i = 0; i < 1000; i++) for (int j = 0; j < 100; j++) for (int k = 0; k < ...
- JVM:从实际案例聊聊Java应用的GC优化
原文转载自美团从实际案例聊聊Java应用的GC优化,感谢原作者的贡献 当Java程序性能达不到既定目标,且其他优化手段都已经穷尽时,通常需要调整垃圾回收器来进一步提高性能,称为GC优化.但GC算法复杂 ...
- 从实际案例聊聊Java应用的GC优化
转自美团点评技术博客:https://tech.meituan.com/jvm_optimize.html 当Java程序性能达不到既定目标,且其他优化手段都已经穷尽时,通常需要调整垃圾回收器来进一步 ...
- 从实际案例聊聊Java应用的GC优化--转
https://tech.meituan.com/jvm_optimize.html 当Java程序性能达不到既定目标,且其他优化手段都已经穷尽时,通常需要调整垃圾回收器来进一步提高性能,称为GC优化 ...
- Hive优化案例
1.Hadoop计算框架的特点 数据量大不是问题,数据倾斜是个问题. jobs数比较多的作业效率相对比较低,比如即使有几百万的表,如果多次关联多次汇总,产生十几个jobs,耗时很长.原因是map re ...
- 数据库优化案例——————某市中心医院HIS系统
记得在自己学习数据库知识的时候特别喜欢看案例,因为优化的手段是容易掌握的,但是整体的优化思想是很难学会的.这也是为什么自己特别喜欢看案例,今天也开始分享自己做的优化案例. 最近一直很忙,博客产出也少的 ...
- Java Web 前端高性能优化(二)
一.上文回顾 上回我们主要从图片的合并.压缩等方面介绍前端性能优化问题(详见Java Web 前端高性能优化(一)) 本次我们主要从图像BASE64 编码.GZIP压缩.懒加载与预加载以及 OneAP ...
- mysql优化案例
MySQL优化案例 Mysql5.1大表分区效率测试 Mysql5.1大表分区效率测试MySQL | add at 2009-03-27 12:29:31 by PConline | view:60, ...
随机推荐
- php Hash Table(三) Hash Table初始化
HashTable初始化,在使用HashTable之前要先执行初始化,下边就看看初始化时都做了什么, Zend/zend_hash.c static const Bucket *uninitializ ...
- python 默认全局变量
python 内置默认全局变量print (vars()) __doc__ #py文件头部的注释 '''我是一个注释例子''' print (vars()) __file__ #当前文件路劲__pac ...
- 密钥文件snk
1.(what)是什么? 由一个程序集的标识组成并通过公钥和数字签名(针对该程序集生成)加强的名称,其中的标识包括程序集的简单文 本名称.版本号和区域性信息(如果提供的话). 2.(why)为什么 ...
- 使用CFURLCreateStringByAddingPercentEscapes进行URL编码
iOS程序访问HTTP资源时需要对URL进行UTF8编码,特酷吧在之前一直都喜欢使用NSString的stringByAddingPercentEscapesUsingEncoding方法进行编码.今 ...
- 浙大PAT-1001
1001. 害死人不偿命的(3n+1)猜想 (15) 卡拉兹(Callatz)猜想: 对任何一个自然数n,如果它是偶数,那么把它砍掉一半:如果它是奇数,那么把(3n+1)砍掉一半.这样一直反复砍下去, ...
- C#委托全解析
什么是委托? 委托类似于C语 ...
- [转载]解析用户生命周期价值:LTV
http://www.sykong.com/2014/07/23144 http://youxiputao.com/articles/1288 http://www.woshipm.com/opera ...
- [译]Node.js面试问与答
原文: http://blog.risingstack.com/node-js-interview-questions/ 什么是error-first callback? 如何避免无休止的callba ...
- lwfs指定特定目录输出
在特定节点启lwfs服务,输出特定的目录 在[root@devcpucs ~]# 节点启lwfs服务,输出指定目录/home/export/online1/systest/swcpucs 1.将gio ...
- PHP基础文件下载类的简单封装
1: <?php 2: /** 3: * [FileDown 公用文件下载方法] 4: * @param [type] $filePath [文件路径(绝对路径或相对路径)] 5: */ 6: ...