当前位置: 首页 > 面试题库 >

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

微生毅然
2023-03-14
问题内容

我一直在研究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,并且对要生成的程序集有着非常密切的了解。



 类似资料:
  • 问题内容: 我正在查看Hibernate 配置属性及其可能的值: 所有这些值做什么? 在Hibernate参考文档只是简单地谈论有关,但并没有说明其他任何值: 创建时,自动将模式DDL验证或导出到数据库。使用时,当明确关闭时,将删除数据库模式。 例如 | | | 我在这些堆栈溢出问题中找到了 非常 有用的解释: Hibernate hbm2ddl.auto可能的值及其作用是什么? 模式未放在hbm

  • 问题内容: 我真的很想了解更多有关更新,导出以及可以提供的值的信息, 我需要知道何时使用更新,何时不使用更新?还有什么选择? 这些是可能在数据库上发生的更改: new tables new columns in old tables columns deleted data type of a column changed a type of a column changed its attrib

  • 问题内容: 该功能在内部如何工作?考虑到内核确实具有访问用户内存空间的特权,它是否使用任何缓冲区还是完成了任何内存映射? 问题答案: 的实现高度依赖于体系结构。 在x86和x86-64上,它只是直接从用户空间地址进行读取并写入内核空间地址,同时如果已配置,则暂时禁用SMAP(超级用户模式访问阻止)。它的棘手部分是将代码放置在特殊区域中,以便页面错误处理程序可以识别其中何时发生错误。发生的内存保护错

  • 问题内容: 例如,这样的地图访问: 在此,第二条件的内容不包括在内。但是,通过放置断点,最终无法进入该块。 该示例不是人为设计的,因为: 如果我们跳过,则在主要读取工作负载时,地图将被不必要地锁定。 如果我们跳过第二个,则对于同一密钥,最昂贵的工作(在这种情况下,是由处理)可能会发生多次,这是不可接受的。 问题答案: 覆盖该分支的一种方法是模拟,模拟版本可以将插入到地图中。因此,在此调用之后再次检

  • 我正试图将eclipse中的java项目导出为可运行的jar,但由于某种原因,可运行的jar无法工作。如果双击可执行jar,它什么也不做。我尝试将所需库提取并打包到生成的JAR中。 所以我也尝试导出一些更简单的项目,那些工作很好。最大的区别是我的真实项目有文件:图像和xml文件。 在代码中引用它们,如下所示:

  • 问题内容: 我在Linux内核代码中遇到了这两个宏。我知道它们是编译器(gcc)进行分支优化的指令。我的问题是,我们可以在用户空间代码中使用这些宏吗?会进行任何优化吗?任何示例都将非常有帮助。 问题答案: 是的他们可以。在Linux内核中,它们被定义为 __builtin_expect宏是使用分支预测的特定于GCC的宏;它们告诉处理器条件是否可能为真,以便处理器可以在分支的正确“侧”上预取指令。