2014-07-02 65 views
2

DU有很多非常有用的方面,包括內置漂亮打印。然而,我很驚訝我簡單的ToString函數使得格式化DU的速度提高了1000倍以上。我錯過了什麼嗎?什麼是sprintf "%A"比我的ToString函數做得更多?F#,辨別聯盟中的sprintf「%A」的性能

type XYZ = 
    |X of float 
    |Y of float*float 
    |Z 

let ar = // some test Array 
    [| for i in 1..3000 do for a in [ X(1.) ; Y(2.,3.) ; Z ] do yield a |] 

let xyzToString (x:XYZ) = 
    match x with 
    |X (a) -> sprintf "X %.1f" a 
    |Y (a,b)-> sprintf "Y (%.1f,%.1f)" a b  
    |Z  -> "Z" 

#time 
ar|> Array.map (fun x -> sprintf "%s" (xyzToString x)) // about 15 ms 
ar|> Array.map (fun x -> sprintf "%A" x)    // about 4000 ms 
+0

相關:http://fsharpnews.blogspot.co .at/2012/01/fast-generic-pretty-printing.html – Goswin

+0

很多解析...並且它與DU無關,但與'sprintf'的工作方式 – Carsten

回答

2

正如@Mau所示,您的比較不是蘋果對蘋果。 printf接受任何類型的參數。你的函數接受一個已知的類型。

如果這成爲你真正的問題,你有興趣在一個小的更乾淨封裝解決方案,你可以做這樣的事情:

type XYZ = 
    |X of float 
    |Y of float*float 
    |Z 

    override this.ToString() = 
     match this with 
     |X (a) -> sprintf "X %.1f" a 
     |Y (a,b)-> sprintf "Y (%.1f,%.1f)" a b  
     |Z  -> "Z" 

... 

ar|> Array.map (fun x -> sprintf "%O" x) 
5

sprintf "%A"做一些reflection在運行時間,以確定被打印的對象的類型和結構,這是非常耗時的。

您的版本在編譯時綁定到特定類型(XYZ),使其更有效。