2016-04-28 75 views
11

[dcc32提示] H2443内联函数“RenameFile”未被扩大 因为单元“Winapi.Windows”没有在指定用途列表为什么Sysutils.RenameFile内联?

我明白,内联函数使代码更快。但我只能在狭窄的地方看到收益。例如在一个大循环中调用一个小函数。

但是如何内联IO功能可以提高速度?我的意思是通过内联RenameFile获得几微秒。但是如果磁盘繁忙,执行该函数本身可能需要几毫秒,甚至可能是几十毫秒。

更重要的是,如果您使用的是RenameFile,那么您可能位于您正在执行其他I/O操作的代码块中。所以,这段代码将花费很多时间。所以,现在的收益更加微不足道。

+0

出于同样的原因,他们宣布它的参数“const”......性能增益可能不是那么有意义,但它或多或少是免费的。 (如果你不知道,当它传递给一个函数时,声明一个字符串参数'const'去掉引用计数的Inc/dec)。 –

+1

@ KenBourassa-CONST实际上做的不仅仅是这些,而且在某些条件下(经常遇到)速度增益很大。 – Ampere

+0

以及它在字符串的上下文中还做了什么?对于一个记录,它将通过地址传递,而不是复制其内容,所以当然,速度增益可能相当大。但是在字符串参数的上下文中,引用计数(和所有相关的)是AFAIK的唯一区别。 –

回答

17

RenameFile是内联的,因为它是对另一个函数的简单调用。

这里是什么样子:

function RenameFile(const OldName, NewName: string): Boolean; 
{$IFDEF MSWINDOWS} 
begin 
    Result := MoveFile(PChar(OldName), PChar(NewName)); 
end; 

通过内联这个函数调用SysUtils.RenameFile得到通过调用替换为WinApi.Windows.MoveFile

这具有以下优点:

  • 你保存在呼叫,而不是两个电话,你只需要一个电话。
  • 您的调用代码大小完全相同。
  • CPU保留分支预测(返回堆栈缓冲区)的返回地址列表;通过消除冗余调用,可以节省此缓冲区中的空间,从而防止调用堆栈变得太深时发生预测失误。
  • 生成的代码较小,因为RenameFile本身被取消。

所以内联是非常值得的麻烦,尤其是在递归代码在调用堆栈可以得到深层的CPU将开始mispredicting的回报,因为返回堆栈缓冲区溢出(一些CPU的只有8项,顶部线CPU有24个条目)。

通常,每个调用另一个例程的例程都应该内联。

一个正确的预测回报需要花费一个周期,一个错误预测会清空管道,花费25个周期或更多;由于返回地址需要从存储器而不是缓冲区中获取,所以会增加进一步的延迟。

你是正确的,这些优点都不会影响磁盘IO代码,但这并没有减少这样的简单重定向函数应该总是内联的事实。

+0

谢谢Johan。在这种情况下,我不得不内联几个我自己的功能。 – Ampere