我读了linux内核文档,这个文件描述了static-key:http://lxr.linux.no/linux+v3.11.1/Documentation/static-keys.txt
那么,static-key和__builtin_expect之间的区别是什么?它们都暗示我们可以使用它们来实现 likyly()和不太可能()。
答案 0 :(得分:5)
__builtin_expect
在代码中引入了一个真正的测试和分支指令,需要由CPU进行评估,而来自更有可能的路径的指令 - be-follow继续预先进入CPU管道。
static_key_*
引入了NOP
指令,该指令在代码中占用足够的空间,以便稍后在运行时修补以添加jmp <label>
。这可用于调整打印调试打印,对常规工作情况无影响,即代码未被调试。
来自Linux kernel documentation for static-keys
,
gcc(v4.5)添加了一个新的'asm goto'语句,允许分支到a 标签:
gcc.gnu.org/ml/gcc-patches/2009-07/msg01556.html使用'asm goto',我们可以创建被采用的分支 默认不采用,无需检查内存。然后,在 运行时,我们可以修改分支站点以改变分支方向。
例如,如果我们有一个默认禁用的简单分支:
if (static_key_false(&key)) printk("I am the true branch\n");
因此,默认情况下不会发出'printk'。和代码 生成的将由单个原子'no-op'指令组成(5个字节 在x86上,在直线代码路径中。当分支'翻转'时, 我们将使用'jump'修补直线代码路径中的'no-op' 对外线真分支的指令。因此,改变分支 方向很昂贵,但分支选择基本上是“免费的”。那 是这种优化的基本权衡。
这种低级修补机制称为“跳转标签修补”,是静态密钥的基础。