2013-05-24 15 views
5

Stavo confrontando le prestazioni degli usi sprintf e sono un po 'turbato da ciò che ho visto. Ho testato i seguenti 4 metodi, passando un'istanza di ClassWithToString in ciascuno (tranne PrintInt, che ha ricevuto il valore intero effettivo).Prestazioni di sprintf vs String.Format

type ClassWithToString() = 
    member this.X = 42 
    override this.ToString() = this.X.ToString() 

let Print item : string = 
    sprintf "%A" item 

let PrintInt item: string = 
    sprintf "%i" item 

let PrintObj item: string = 
    sprintf "%O" item 

let Format item : string = 
    System.String.Format("{0}", item) 

I risultati per 50.000 iterazioni:

Print (%A):  3143ms 
PrintInt (%i): 355ms 
PrintObj (%O): 384ms 
Format:   8ms 

Per "Print" Capisco% A sta usando riflessione in modo che la lentezza non è scioccante, anche se per 50k iterazioni Sono rimasto sorpreso del totale tempo. In seguito, "PrintInt" e "PrintObj" non usano la riflessione e quindi sono di un ordine di grandezza più veloce, il che ha anche senso.

La parte che mi confonde è che alla luce dei risultati dello String.Format() sprintf in generale sembra essere terribilmente lento (ed è stato visto nei profili delle applicazioni live). Perché le grandezze sprintf sono più lente di String.Format()? C'è un'alternativa migliore nello spazio F # che ho perso?

+0

Poiché sai già che utilizza Reflection, che cosa stai cercando esattamente? – Daniel

+1

Confrontate la [fonte '' printf'] (https://github.com/fsharp/fsharp/blob/master/src/fsharp/FSharp.Core/printf.fs) con quella di 'StringBuilder.AppendFormat'. 'printf' fa molto di più, ad esempio, la stampa di raccolte ricorsive. – Daniel

+1

Solo% A utilizza la riflessione. % sarei il caso base. – roken

risposta

7

Solo% A utilizza la riflessione. % sarei il caso base.

Non è vero. Tutte le funzioni printf devono riflettere per costruire funzioni di stampa di tipo sicuro dalle stringhe di formato, indipendentemente dagli specificatori che si utilizzano. Dai uno sguardo a this line e this line dal modulo printf per ulteriori approfondimenti. Quindi è facile capire perché sprintf "%i" è ancora più lento di String.Format. Nel caso di sprintf "%A", ha un altro livello di riflessione che spiega la sua terribile lentezza.

Esiste un'alternativa migliore nello spazio F # che ho perso?

Se il vostro scopo è quello di costruire grandi archi, StringWriter e StringBuilder sono probabilmente la strada da fare. Se si esegue il benchmark per lo scopo di registrazione, FastPrintf è una libreria promettente. Puoi provare this NuGet package che afferma di essere 100 volte più veloce delle funzioni integrate printf.