2011-05-24 107 views
3

在這個問題Why is this F# code so slow?中,討論結構比較使功能let min3(a, b, c) = min a (min b c) 慢;不應該簡單類型的結構比較與原生類型一樣快嗎? 我很困惑,因爲人們談論的總是使用HashIdentity.Structural作爲F#中的字典FSharp runs my algorithm slower than Python。如果我有一個簡單類型(int或字符串)作爲密鑰的字典,使用HashIdentity.Structural會對性能造成影響嗎?F#簡單類型和結構比較

回答

3

一般來說,我不會擔心比較的性能,因爲對於典型的代碼比較來說,不太可能是性能瓶頸。如果你確定你有一個性能問題,並且分析顯示比較是原因,那麼你可以考慮如何最好地解決它。

如果您確實需要考慮比較的性能,那麼您可能需要了解編譯器的工作方式。在您引用的第一個示例中,min3函數的類型爲'a * 'a * 'a -> 'a when 'a : comparison。該功能將被編譯採取泛型類型這將是這個樣子在C#中的3個參數的.NET方法:

using LP = Microsoft.FSharp.Core.LanguagePrimitives; 

T min3<T>(T a, T b, T c) { 
    T d = LP.HashCompare.GenericLessThanIntrinsic(b,c) ? b : c; 
    return LP.HashCompare.GenericLessThanIntrinsic(d,a) ? d : a; 
} 

GenericLessThanIntrinsic方法也是通用的,並在其中必須有執行邏輯根據所比較的實際類型進行比較。這可能需要一些類型測試和虛擬方法調用。這些並不是非常昂貴的操作,但它們比直接比較兩個整數值要慢得多。因此,如果比較佔工作量的很大一部分,那麼使用通用比較例程可能會對整體性能產生重大影響,並且專門將min3函數僅用於整數而不是任何通用值可能會是一個巨大的性能優勢。同樣,如果您只是將整數存儲爲字典密鑰,那麼使用內置的GetHashCode()Equals()實現(這是字典將默認執行的操作)將比使用結構比較更快。但是,這對你來說是否是一個重要的區別取決於你正在編寫的實際代碼 - 正如我之前所說的,關鍵比較佔用算法運行時間的一個重要部分是有點不尋常的。