代码里写很多if会影响效率吗?

关注者
243
被浏览
62,383

33 个回答

看你怎么写 if.

嵌入很多层if的代码叫做“箭头代码”,是一个anti-pattern。 这种代码会增加程序的循环复杂度 (Cyclomatic complexity

具体可以看这里:

Flattening Arrow Code

这里:

wiki.c2.com/?


总的来说,程序里用if-else是有开销的。每次condition的判断就是一个计算,但是if-else的存在增加了程序语言的表达能力,提高了开发效率。


如果纯粹从性能的角度看,不用if-else肯定比用好。但是在某些情况下CPU可以做到让程序性能近似于没有if-else的情况。stackoverflow上有一个经典问题:

Why is it faster to process a sorted array than an unsorted array?

现代CPU在运行到if的时候,不会先判断condition然后再选择进入if-else的哪一个分支。它们真正做的是直接进入一个分支执行,如果猜错则回滚此分支的操作然后换另一个分支执行。如果CPU每次都猜对,就会让程序性能接近没有if-else的情形;反之则会造成开销。那么如何让CPU猜对呢?如果condition 大部分时间都是true,少部分时间是false,那么CPU 就比较好猜,反之,如果condition的值是一个随机值,那么CPU每次就得“瞎猜”,猜对的概率就会低了。


当然,如果你的if-else不是出现在循环里,一般不会造成太大开销。



=============分割线==============================

回答一下讨论区里的问题。因为我也不是做CPU的,就当抛砖引玉。希望大家指正!

首先CPU遇到if时继续执行这个技术叫做分支预测 (branch prediction),具体可以看下面的链接:zh.wikipedia.org/zh-cn/


现代CPU运行时不是一条命令一条命令的执行,而是一下读进多条命令,并且对这些命令进行优化,生成流水线(pipeline)。优化后的流水线的运行效率是非常高的。生成流水线也是一个耗时的工作。CPU遇到if的条件语句时根据分支预测器的结果选择跳转还是不跳转。并且把相应分支里的命令载入生成流水线。CPU同时还会并行地执行条件语句。如果对就继续执行,如果错就把当前分支的流水线抛弃然后载入另一个分支生成流水线。所以如果每次都猜对,程序的运行效率就会基本和没有if差不多。

会有一些开销,主要是可能破坏cpu的流水线执行,影响预读和cache命中。一般cpu会有些分支预测的策略,大部分情况下命中率是比较高的,也可以在代码中进行分支提示。如果你很在乎这部分性能,可以用这个

gcc的源码里有很多例子。

不过对大多数业务,除非是特别吃cpu的场景,都不需要搞这些。