为什么强制内联函数会导致性能不佳?

Why can forced inline functions lead to bad performance?

如果我内联一个函数。 函数调用主体将被复制,而不是向它发出 call()。 为什么这会导致性能不佳?

编辑:那么由于大函数导致的缓存未命中呢? 为什么经验法则 "only inline functions with max 3 lines" 存在?

在现代 C++ 编译器中没有强制内联函数的标准方法,因此这是一个有争议的问题。但是,假设您正在使用特定于编译器的功能来强制内联(并且编译器不会忽略它),它不会导致性能下降,但会由于相同代码的更多副本而导致可执行文件大小增加。

编辑:根据下面的评论,应该提到的是,确实存在一种非常不可能的边缘情况,您的代码可能会非常接近地执行同一内联函数的不同副本,从而降低指令缓存的效率。这会显着影响性能的可能性非常小,但在某些极端情况下可能会。

可能存在一种边缘情况,即内联函数会增加程序大小或移动程序的位,从而使缓存未命中发生在以前不会发生的地方。这并不常见,因为缓存旨在处理最常见的情况,并且与大多数热点相比相当大。

我们应该退后一步,尝试解释 CPU 的工作原理。通常它们有不同的缓存,一个用于代码,告诉 CPU 需要执行的指令,另一个用于数据,即应用操作的地方。

数据缓存未命中是"easy"要解决的问题,尽量使用尽可能小的数据结构,将访问频率较高的成员放在一起...

指令缓存未命中更难理解和解决,这也是人们普遍认为 C++ 中的多态行为比正常函数调用慢的原因。基本上 CPU 将在其缓存中预取存储在您尝试执行的执行点附近的指令,如果所有内容都是内联的,则只有更多数据并且它将无法预取所有内容,导致缓存未命中。请注意,这只是一个简单的案例,根据我的经验,我遇到了模板实例化的问题,它会生成大量代码,导致性能比仅具有简单的虚拟调用和不太深的对象层次结构要慢。

正如 Alexandrescu 经常指出的那样,您应该始终为您的代码计时

来源: What Every Programmer Should Know About Memory