2016-04-28 80 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