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