Linux内核中可能/不太可能的宏如何工作以及它们的好处是什么?

我一直在挖掘Linux内核的某些部分,发现这样的调用:

if (unlikely(fd < 0))
{
    /* Do something */
}

要么

if (likely(!err))
{
    /* Do something */
}

我找到了它们的定义:

#define likely(x)       __builtin_expect((x),1)
#define unlikely(x)     __builtin_expect((x),0)

我知道它们是为了优化,但它们是如何工作的?使用它们可以预期性能/尺寸减少多少?至少在瓶颈代码中(当然在用户空间中)是否值得麻烦(并且可能失去可移植性).

最佳答案
它们暗示编译器发出的指令将导致分支预测有利于跳转指令的“可能”侧.这可能是一个巨大的胜利,如果预测是正确的,这意味着跳转指令基本上是免费的并且将采用零周期.另一方面,如果预测是错误的,则意味着需要刷新处理器流水线并且可能花费几个周期.只要预测在大多数情况下是正确的,这将有利于性能.

像所有这些性能优化一样,您应该只在进行大量分析后才能确保代码真正处于瓶颈状态,并且可能具有微观特性,即它在紧密循环中运行.通常Linux开发人员都很有经验,所以我想他们会这样做.他们并不太关心可移植性,因为他们只针对gcc,他们对他们想要生成的程序集非常了解.

转载注明原文:Linux内核中可能/不太可能的宏如何工作以及它们的好处是什么? - 代码日志