目前代码如下
for(let i=0;i<length;i++) {
if(flag()){
foo();
}
bar();
}
简单来说,就是在循环中每次都会去判断一个条件,用来确定是否需要多一步操作。但实际上这个条件是在循环开始前就已经可以确定的了。 这样的代码还可以进一步优化吗?目前想到的是根据条件拆成两个循环,但循环内的代码又高度重复了。
1
hundandadi 308 天前
1. flag() 如果与 i 有关
2.bar()是否有执行条件 这写的不是挺好的吗。清晰明了。flag() 如果与 i 有关那就没啥问题,bar()是否有执行条件 |
2
crayygy 308 天前 via iPhone
我记得以前测试过,分成两个循环分别调用不同的处理效率可能更高,再就是 flag() 函数如果是一个确定且和 i 没关系的话,可以用一个变量来代替,避免重复计算
|
3
luoshuitianyi 308 天前 1
说实话应该没有更好的办法,效率和代码简洁只能取其一。从逻辑上来讲就是分支放在循环外还是内的问题。
如果放在内,不论在哪一步都会进行 length 次判断。如果放在外,那在不同分支肯定都要写代码,这就无法保证代码简洁性。 所以不想因为反复进行条件判断而导致效率降低的话,只能选择后者。 |
4
okakuyang 308 天前 via iPhone
没有优化空间
|
5
wangtian2020 308 天前
如果与 i 有关应该没啥性能损失,不需要优化
如果与 i 无关可以减少不必要的计算 ``` let flagTemp = flag() for(let i=0;i<length;i++) { if(flagTemp){ foo(); } bar(); } |
6
chesha1 308 天前
你拆成两个,看一下汇编是不是一样就行了,我感觉这么简单的优化,编译器是能做的,自己测试一下呗
|
7
persimmon 308 天前
depends on 你具体的上下文,foo 和 bar 是不是纯函数? foo 或 bar 执行的时候会不会影响 flag 返回的结果,确定以后再考虑是否单独分出来
|
8
ns09005264 308 天前
```javascript
let f; if (flag()) { f = () => { foo(); bar(); }; } else { f = () => bar(); } for (let i = 0; i < length; i++) { f(); } ``` |
9
leonshaw 308 天前 via Android
注意 i < length 也判断了 length 次,相信 CPU 的分支预测能力
|
10
Tsccai OP flag()其实我确实是处理为一个变量,而且它完全不会受到 foo()和 bar()的影响。实际上,这个 flag 在程序最开始执行的时候就已经确定了,它取决于用户的原始输入。
感谢各位,看来确实是没有多少优化的空间了。 |
11
Al0rid4l 307 天前
这种时候你需要的是宏这样的东西, 两个循环, 但复用大部分代码
|
12
RecursiveG 307 天前
Benchmark 表示开了优化没啥区别: https://gist.github.com/RecursiveG/5361f6da8814f3f11bb63581f401cd87
|