前言
在开发中,经常会遇见嵌套循环,但是嵌套循环也存在着效率问题,比如大循环放外面还是放里面,也决定了效率问题,还有一些嵌套循环是可以避免掉的。
案例
这里使用了一个简单的例子,执行同样的次数,但拆分成两个循环,一个大循环一个小循环,来模拟嵌套循环
大循环在内的代码
public static void main(String[] args) {
long sum =0;
for (int k=1;k<=10000;k++){
long timestamp = System.currentTimeMillis();
int count =1;
for(int i = 0;i<5;i++){
for (int j=0;j<1000000;j++){
count++;
}
}
timestamp = System.currentTimeMillis() -timestamp;
System.out.println("第"+k+"次大循环在内消耗时间:"+timestamp+"ms,count="+count);
sum +=timestamp;
}
System.out.println("=========================================");
double age = (double) sum /10000;
System.out.println("大循环在内总耗时"+sum+"ms,平均时长:"+age+"ms");
}
大循环在外的代码
public static void main(String[] args) {
long sum =0;
for (int k=1;k<=10000;k++){
long timestamp = System.currentTimeMillis();
int count =1;
for(int i = 0;i<1000000;i++){
for (int j=0;j<5;j++){
count++;
}
}
timestamp = System.currentTimeMillis() -timestamp;
System.out.println("第"+k+"次大循环在外消耗时间:"+timestamp+"ms,count="+count);
sum +=timestamp;
}
System.out.println("=========================================");
double age = (double) sum /10000;
System.out.println("大循环在外总耗时"+sum+"ms,平均时长:"+age+"ms");
}
可以思考一下哪个速度会更快?
3
2
1
答案揭晓~
大循环在外的执行时间,总耗时3811ms
大循环在内的执行时间,总耗时6ms
在此可以得知,在进行循环时,在大循环放在里面,会大大加快程序执行的时间。
原因
既然得知了结果,也需要了解一下为什么这样做速度会更快的原因。现在,基本上CPU内部都有分支指令预测,就是当执行到转移指令时,都会直接从分支目标缓存中取出目标指令的地址,然后将要执行的指令提前预取到CPU的指令预取指令队列中。
简单来说,一个100次的一层循环在执行时,除了在第一次和最后一次会预测错误外,其他8次都会预取成功,避免了执行转移指令时重新取出新指令造成的时间浪费。
这里将大循环在外称为A,大循环在内称为B,次数都为1000000*5,以下将1000000称为i,5称为j。A最终预测失败的次数是j * 2+2,B最终预测失败的次数i * 2+2。
可能还有人会疑惑,这样来说,那不应该是A的预测失败次数更少吗?具体是怎么算出来的?
简单的说一下我自己的理解,也就是A的外层执行了j次,预测失败的次数确实为2,但是它执行了j次i循环,i循环每次都会预测失败两次,所以最终结果为i * 2+2,相反,B的外层执行了j次,最终结果j * 2+2。i比j的差距越大,效率差距越明显。
总结
在遇到无法避免的循环时,可以将大循环放置在里面,小循环放在外面以此来提高运行速度。