Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Performance of sprintf vs String.Format [duplicate]

I was comparing the performance of sprintf usages and am a little troubled by what I saw. I tested the following 4 methods, passing an instance of ClassWithToString in to each (except for PrintInt, which received the actual integer value).

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)

The results for 50,000 iterations:

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

For "Print," I understand %A is using reflection so the sluggishness there is not shocking, though for 50k iterations I was surprised at the total time. Following that, "PrintInt" and "PrintObj" do not use reflection and thus are an order of magnitude faster, which also makes sense.

The part that confounds me is that in light of the results of String.Format() sprintf in general appears to be dreadfully slow (and has been witnessed in profiles of live applications). Why is sprintf magnitudes slower than String.Format()? Is there a better alternative in the F# space that I've missed?

like image 518
roken Avatar asked May 24 '13 19:05

roken


People also ask

Is sprintf faster?

It is more than 6 times slower than fmt::format_int . One possible reason for this is that sprintf parses the format string, but so do fmt::format and fmt::format_to which are 1.8 - 2.6 times faster than sprintf . The good thing is that you don't have to use sprintf in an attempt to sacrifice safety for performance.

Is string format fast?

Generally you should use String. Format because it's relatively fast and it supports globalization (assuming you're actually trying to write something that is read by the user).

Is string format expensive?

toString() has the best score of 0.953 milliseconds. In contrast, a conversion which involves String. format(“%d”) has the worst performance. That's logical because parsing the format String is an expensive operation.


1 Answers

Only %A uses reflection. %i would be the base case.

It's not true. All printf functions need reflection to construct type-safe printing functions from format strings, no matter which specifiers you use. Take a look at this line and this line from printf module for more insights. So it's easy to see why sprintf "%i" is still slower than String.Format. In the case of sprintf "%A", it has one more level of reflection which explains its dreadful slowness.

Is there a better alternative in the F# space that I've missed?

If your purpose is to construct big strings, StringWriter and StringBuilder are probably the ways to go. If you benchmark for logging purpose, FastPrintf is a promising library. You can try out this NuGet package which claims to be 100x faster than the built-in printf functions.

like image 149
pad Avatar answered Oct 01 '22 13:10

pad