我最近遇到了一個意想不到的代碼優化,想檢查我對我所觀察的內容的解釋是否正確。以下是的情況另一個具有更加簡化例如:F#自動泛化和性能
let demo =
let swap fst snd i =
if i = fst then snd else
if i = snd then fst else
i
[ for i in 1 .. 10000 -> swap 1 i i ]
let demo2 =
let swap (fst: int) snd i =
if i = fst then snd else
if i = snd then fst else
i
[ for i in 1 .. 10000 -> swap 1 i i ]
的代碼2塊之間的唯一區別是,在第二種情況下,我明確聲明交換的參數作爲整數。然而,當我用#time在fsi中運行2個片段時,我得到:
案例1實際:00:00:00.011,CPU:00:00:00.000,GC gen0:0,gen1:0,gen2: 0
案例2真:00:00:00.004,CPU:00:00:00.015,GC GEN0:0,GEN1:0,第2代:0
即第2段運行速度比第一快3倍。這裏的絕對性能差異顯然不是問題,但如果我使用交換功能很多,它會堆積起來。
我的假設是性能受到打擊的原因是,在第一種情況下,swap是通用的並且「需要相等」,並檢查int是否支持它,而第二種情況不需要檢查任何內容。這是發生這種事的原因,還是我錯過了別的東西?更一般地說,我應該認爲自動泛化是一把雙刃劍,也就是一個可能會對性能產生意想不到影響的令人敬畏的功能?
感謝指向另一個問題,確實非常相似。所以,如果我理解正確,標記一個函數爲內聯說:「而這個函數是通用的,創建一個特定的版本基於它使用的類型稱爲」?那麼是否有理由不將每個數學樣式函數標記爲內聯? – Mathias
或者換句話說,你能否詳細說明「它不會產生太多的代碼」,我不太明白。 – Mathias
@Mathias「inline」關鍵字表示編譯器將用其實現替換對函數的調用。這意味着函數的代碼將在每次調用時重複一次。對於真正長的函數,這可能會使程序集更大(或生成更長時間的JIT的更長方法)。這就是爲什麼我建議僅將這個功能用於更簡短的功能 - 您示例中的功能對我來說很短暫。 –