Delphi 为什么Sysutils.RenameFile是内联的?

Delphi 为什么Sysutils.RenameFile是内联的?,delphi,inline,Delphi,Inline,[dcc32提示]H2443内联函数“重命名文件”尚未展开 因为在使用列表中未指定单元“Winapi.Windows” 我知道内联函数可以使代码更快。但我只看到了一些小地方的收益。例如,在大循环中调用小函数 但是如何内联IO函数来提高速度呢?我的意思是通过内联重命名文件,您可以获得几微秒。但是执行函数本身可能需要几毫秒,如果磁盘繁忙,甚至可能需要几十毫秒 更重要的是,如果您使用的是RenameFile,那么您可能正在执行其他I/O操作的代码块中。因此,这段代码将花费大量时间。因此,现在的收益更加

[dcc32提示]H2443内联函数“重命名文件”尚未展开 因为在使用列表中未指定单元“Winapi.Windows”

我知道内联函数可以使代码更快。但我只看到了一些小地方的收益。例如,在大循环中调用小函数

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


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

重命名文件
是内联的,因为它是对另一个函数的简单调用

下面是它的样子:

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将开始预测错误的返回,因为返回堆栈缓冲区溢出(一些CPU只有8个条目,最上面的CPU有24个条目)

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

一个正确预测的回报成本为一个周期,一个预测失误清空管道,成本为25个周期或更多;由于需要从内存而不是从缓冲区获取返回地址,因此会增加更多的延迟


这些优点在磁盘IO代码中都不重要,这是正确的,但这并不影响这样的简单重定向函数应该始终内联。

谢谢Johan。在本例中,我有几个自己的函数需要内联。出于同样的原因,它们声明了它的参数
const
。。。性能增益可能没有那么大意义,但它或多或少是免费的。(如果您不知道,声明一个字符串参数
const
在传递给函数时删除其引用计数的Inc/dec)。@KenBourassa const实际上做的不止这些,并且在某些条件下(经常遇到)速度增益很大。在字符串上下文中它还能做什么?对于一个记录,它将通过地址传递,而不是复制它的内容,所以是的,当然,速度的提高是相当大的。但是在字符串参数的上下文中,引用计数(以及所有相关的内容)是AFAIK的唯一区别。当您不使用CONST时,可能会创建字符串的副本。康斯特永远不会这样。在循环中,如果传递的参数是一个长字符串,那么速度影响可能很大。有什么来源吗?我可以看到宽字符串和短字符串的情况。。。但对于字符串,我不记得看到或听到过任何会导致创建字符串副本的情况。(即,在可以声明参数
const
的所有情况下)