sprintf与String.Format的性能

时间:2013-05-24 19:18:59

标签: .net string performance f#

我正在比较sprintf用法的性能,并且对我看到的东西感到有点困扰。我测试了以下4种方法,将ClassWithToString的实例传递给每个(除了接收实际整数值的PrintInt)。

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)

50,000次迭代的结果:

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

对于“打印”,我理解%A正在使用反射,因此那里的迟缓并不令人震惊,但是对于50k次迭代,我对总时间感到惊讶。在此之后,“PrintInt”和“PrintObj”不使用反射,因此速度提高了一个数量级,这也很有意义。

令我感到困惑的部分是,鉴于String.Format() sprintf的结果总体上看起来非常缓慢(并且已经在实时应用程序的配置文件中见证过)。为什么sprintf幅度比String.Format()慢?我错过了F#空间有更好的选择吗?

1 个答案:

答案 0 :(得分:7)

  

只有%A使用反射。 %i将是基本情况。

这不是真的。无论您使用哪种说明符,所有printf函数都需要反射以从格式字符串构造类型安全的打印函数。请查看printf模块中的this linethis line,了解更多见解。因此,很容易看出为什么sprintf "%i"仍然比String.Format慢。 在sprintf "%A"的情况下,它有一个更高层次的反射,这解释了它可怕的缓慢。

  

我错过了F#空间中有更好的选择吗?

如果您的目的是构建大字符串,那么StringWriterStringBuilder可能是最佳选择。如果您为记录目的进行基准测试,FastPrintf是一个很有前途的库。您可以试用this NuGet package声称比内置printf功能快100倍。