1

我最近看到Util我朋友写的一个类有这么多inline方法。这门课是关于图像的,并且有类似的方法

public static inline function resize ( img:Image, width:Int, height:Int)
{
    //... method implementation goes here.
}

我问他为什么要使用inline. 我知道编译器会改变

var img:Image = ImgUtil.resize(img, 100, 100);

var img:Image = // Implementation of method here

他只是说它减少了对函数的调用,并且只在实用方法上使用它们。每次复制相同的代码不会增加程序大小吗?

现在需要这个吗?如果需要,什么时候应该使用它们?

编辑

我在 Patrick 提供的链接中列出的列表中列出了最多的问题和优势,以帮助不想通过链接的未来观众。

问题

用扩展的函数体替换调用站点可能会以多种方式降低性能:

  • 在代码大小比速度更重要的应用程序中,例如许多嵌入式系统,内联通常是不利的,除了非常小的函数,例如琐碎的 mutator 方法。
  • 代码大小的增加可能会导致一小部分关键代码部分不再适合缓存,从而导致缓存未命中和速度减慢。
  • 内联过程中添加的变量可能会消耗额外的寄存器,并且在寄存器压力已经很高的区域中,这可能会强制溢出,从而导致额外的 RAM 访问。
  • 语言规范可能允许程序对过程的参数做出额外的假设,这些假设在过程被内联后不能再做出。
  • 如果代码大小增加太多,可能会超出 RAM 大小等资源限制,从而导致程序无法运行或导致抖动。今天,除了非常激进的内联之外,这不太可能成为台式机或服务器计算机的问题,但它仍然可能是嵌入式系统的问题。

通常,编译器开发人员会牢记这些问题,并在他们的编译器中加入启发式方法,在大多数情况下选择内联哪些函数以提高而不是恶化性能。

优点:

内联扩展本身是一种优化,因为它消除了调用的开销,但它作为一种启用转换更为重要。也就是说,一旦编译器在其调用站点的上下文中扩展了一个函数体——通常带有可能是固定常量的参数——它可能能够进行以前不可能的各种转换。例如,在这个特定的调用站点,条件分支可能总是为真或总是为假。这进而可以实现死代码消除、循环不变代码运动或归纳变量消除。

4

1 回答 1

0

维基百科会告诉你比你需要的更多。

于 2013-05-21T06:36:28.843 回答