【问题标题】:Is there an actual example where inline is detrimental to the performance of a C program?是否有一个实际示例说明内联对 C 程序的性能有害?
【发布时间】:2014-08-18 14:31:25
【问题描述】:

在许多关于函数声明中的inline 关键字的辩论中,有人会指出它实际上会使您的程序在某些情况下变慢——如果我是正确的话,主要是由于代码爆炸。我自己在实践中从未遇到过这样的例子。使用inline 可能会损害性能的实际代码是什么?

【问题讨论】:

  • 请注意inline 只是一个建议;编译器可以随意忽略它。
  • 有许多编译单元都包含相同的大内联方法并且只使用一次,那么你可能有一个退化的例子......仍然取决于不做链接时间代码生成等东西。
  • 正如@dan04 所说,编译器不需要听你的,通常它很聪明。
  • 很多地方,比如 max function ('int max(int a, int b)') 可以直接内联(实际上也可以定义为宏,效果一样)。程序不会“跳转”到内存中的那个函数,也不会用变量加载堆栈。大量使用。
  • 当然内联可能是有害的 - 如果不是,编译器(或开发人员)将始终内联所有内容。它增加了寄存器压力和代码大小/L1i 缓存占用空间,其中任何一个都很容易成为比函数调用开销更大的性能问题。坦斯塔夫。

标签: c performance optimization inline-functions


【解决方案1】:

整整 10 年零一天前,我在 OpenBSD 中做了这个提交:

http://www.openbsd.org/cgi-bin/cvsweb/src/sys/arch/amd64/include/intr.h.diff?r1=1.3;r2=1.4

提交信息是:

deinline splraise、spllower 和 setsoftint。 使内核更小更快。 deraadt@好的

据我所知,内核二进制文件缩小了 100kB 以上,并且没有一个测试用例会变得更慢,并且几个宏基准测试(如编译内核)明显更快(如果我没记错的话,5-10% ,但不要引用我的话)。

大约在同一时间,我开始着手实际测量 OpenBSD 内核中的内联函数。我发现有一些性能提升很小,但大多数的可测量影响为 0,并且有几个使事情变得更慢并被杀死。至少还有一个 uninlining 产生了巨大的影响,其中一个是内部 malloc 宏(如果它的大小在编译时已知,这个想法是内联 malloc)和数据包缓冲区分配器,它们将内核缩小了 150kB 并具有显着的性能改进。

可以推测,虽然我没有证据,但这是因为内核很大,在执行系统调用时我们很难留在缓存中,每一点都有帮助。所以在这些情况下真正有帮助的只是二进制文件的缩小,而不是执行的指令数量。

【讨论】:

  • 多年前在 linux 内核中也进行了类似的移除内联更改。
【解决方案2】:

想象一个没有参数的函数,但需要进行密集计算,中间值或寄存器使用数量一致。然后在具有一致数量的中间值或寄存器使用的代码中内联该函数。

没有参数使调用过程更加轻量,因为不需要耗时的堆栈操作。

当内联时,编译器必须保存许多寄存器,并溢出其他寄存器以与新函数一起使用,从而以最糟糕的方式重现函数调用所需的寄存器和数据备份过程。

如果备份操作在时间和机器周期方面比函数调用机制更广泛,特别是如果函数被广泛调用,那么就会产生不利影响。

这似乎是操作系统中主要使用的某些特定功能的情况。

【讨论】:

    猜你喜欢
    • 2013-07-26
    • 1970-01-01
    • 1970-01-01
    • 2013-01-01
    • 2019-06-22
    • 1970-01-01
    • 2011-02-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多