第 120 题:为什么 for 循环嵌套顺序会影响性能?
var t1 = new Date().getTime() for (let i = 0; i < 100; i++) { for (let j = 0; j < 1000; j++) { for (let k = 0; k < 10000; k++) { } } } var t2 = new Date().getTime() console.log('first time', t2 - t1) for (let i = 0; i < 10000; i++) { for (let j = 0; j < 1000; j++) { for (let k = 0; k < 100; k++) { } } } var t3 = new Date().getTime() console.log('two time', t3 - t2)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(32)
我在网上看到的文章都是这样说的,let 每一轮都是一个新声明的变量的,你看看这里
还有这里
预测,不能保证百分之百,就像天气预报似的,刷新一次,会有不同的结果。
噢噢,let 每次循环都会初始化,var 是每个for循环只初始化一次
我测试了一下 使用var和let的区别,为什么var比let性能差那么多呀?有大佬知道吗?
内循环多的话,在跳出内部循环的之前,会动态记录和调整转移指,这部分工作需要消耗一定的时间,第二个 内循环跳出的次数多,导致耗时较多。
初始化值是正解啊
这... 难道是我的chrome比较新?为什么得到的答案完全不一样
for循环中使用let,js引擎会为每一次循环初始化一个独立作用域和变量。
所以,第一种情况:
i 初始化次数:100,j 初始化次数:100 * 1000,k 初始化次数:100 * 1000 * 10000
第二种情况:
i 初始化次数:10000,j 初始化次数:10000 * 1000,k 初始化次数:10000 * 1000 * 100
通过比较可得
第二种情况,需要初始化的次数较多,所以耗时较长。
我测试了很多次,发现每次的结果都不尽相同。但是当循环次数到达亿级的时候试了很多次输出的结果没有嵌套的比嵌套的使用时间更长。有大佬知道为什么吗?
学习了,for的嵌套顺序不同,原来是因为每个值初始化的次数不一样,学习了
同问为什么 var 和 let 时间差这么多,一直以为 var 用在循环里面会比较好,哪位大佬来解惑
你说的两个循环的次数的是一样的,可是我打印出来的a,b的数值是不一样的,这是为什么呢?
因为你这累加不对:
前两个累加去掉才一样,是 6000
(一)var a = 1000100100 = 100 + 1001000 + 100100010000;
(二)var b = 1010010000 = 10000+100001000+100001000100;
a<b
但大头100001000100不变
应该不是吧, let是每次循环都会声明一个新的 i 、j 、 K ,所以
有趣的还有 , 为什么你的5000+ms 我这只有 几百呀 , 哈哈
每一次for循环只会初始化一次而已。后面的循环是不会初始化。
可以参考这本书
按照你的示例,结果却是相反的。
但是我觉得按照这个说法好像不能很好地解释题目三层嵌套的情况
从数学的角度分析,已知for循环执行顺序,1:执行变量(仅执行一次)2:执行条件 3:执行代码块区域 4:最后执行++,当执行到第三步时,发现有一个for循环,程序会先执行完内部所有循环 ,之后返回到外部循环。设单次循环执行步骤2和步骤4的时间为T0,内层循环执行代码块区域的时间为T1,内层循环执行的次数为M ,中间层循环执行的次数为N,外层循环执行的次数为X,那么内层循环执行的总次数为MNX,中间层为MX,外层为X,所以循环的总次数为MNX+NX+X,总时间T是执行循环步骤的总时间加上执行代码区域的总时间,即T=(MNX+NX+X)T0+MNXT1,这里代码不变时,T0和T1不变, 总次数MNX不变,(NX+X)越小,所耗费的时间也会越少。
有趣的是在火狐下两次时间差不太多
你可以减少次数测试一下,当单循环次数过大,在相同循环次数的情况下,单循环性能比多循环次数差。可能是一个内存空间存放不了过大的数值,再调用一个内存空间。
第二循环
变量 实例化(次数) 初始化(次数) 比较(次数) 自增(次数)
i 1 1 1000 1000
j 1000 1000 1000 * 100 1000 * 100
k 1000 * 100 1000 * 100 1000 * 100 * 10 1000 * 100 * 10
第一循环
变量 | 实例化(次数) | 初始化(次数) | 比较(次数) | 自增(次数)
i | 1 | 1 | 10 | 10
j | 10 | 10 | 10 * 100 | 10 * 100
k | 10 * 100 | 10 * 100 | 10 * 100 * 1000 | 10 * 100 * 1000
主要差别是外层两个变量初始化,比较,自增次数全部减少
坐等大佬
有没有大佬讲讲for循环嵌套循环相同循环次数,外层越大,越影响性能的原理是什么,比如V8引擎编译机智?或者什么因素的影响,挺好奇的
这里说说我个人的理解:对于这个例子,接下来我们利用三个例子来推算
首先我们单独来比较最内层的循环,也就是循环 10000 次和 100 次的时长
单独循环 10000 和 100 的时间是相差无几的,基本可以看成一个等量关系。那么差异肯定是在外层嵌套的两个循环了。
我们再来看看另外一个例子:两层嵌套遍历,外层循环次数是 1000,里层循环次数一个是 10000,另一个是 100
差异就出来了,明显看到循环差异在 2-4 ms,可以看到当外层循环的次数一样是,循环的时长取决于里层循环,里层循环次数越多,执行时间越长。
我们再来看看这样一个例子:两层嵌套循环,里层的循环次数都是 1000,外层循环次数一个是 10000,一个是 1000
差异就出来了,明显看到循环差异在 2-4 ms,可以看到当内层循环的次数一样是,循环的时长取决于外层循环,外层循环次数越多,执行时间越长。
====== 以上结论都可以根据算法的时间复杂度计算规则得到 =====================================
我尝试了一下只有一层不嵌套的情况,得到的结果似乎不似预期,我认为性能应该是跟执行的次数有关,但是执行相同的次数,没有嵌套的反而是相对时间比较多的
两个循环的次数的是一样的,但是 j 与 k 的初始化次数是不一样的
所以相同循环次数,外层越大,越影响性能
应该是第一个时间少一点,比如,按照每次循环判断来说 (初始化 自增次数类似)
1、i会循环100次,判断i<100 100次
j会循环100 * 1000次,判断j<100 100 * 1000次
k会循环100 * 1000 * 10000次,判断k<100 100 * 1000 * 10000次
2、i会循环10000次,判断i<100 10000次
j会循环10000 * 1000次,判断j<100 10000 * 1000次
k会循环100 * 1000 * 10000次, 判断k<100 100 * 1000 * 10000次
虽然判断k<100的次数都是一样的 但是前面两种判断就不一样了,由此可以看见时间长短。
循环次数少的放在外层,减少内层变量的操作(初始化,比较,自增等)次数吧。
为什么