sprintf与String.Format的性能

rok*_*ken 5 .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)
Run Code Online (Sandbox Code Playgroud)

50,000次迭代的结果:

Print (%A):     3143ms
PrintInt (%i):   355ms
PrintObj (%O):   384ms
Format:            8ms
Run Code Online (Sandbox Code Playgroud)

对于"打印",我理解%A正在使用反射,因此那里的迟缓并不令人震惊,尽管对于50k次迭代我总是惊讶于总时间.在此之后,"PrintInt"和"PrintObj"不使用反射,因此速度快一个数量级,这也是有意义的.

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

pad*_*pad 7

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

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

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

如果您的目的是构造大字符串,那么StringWriterStringBuilder可能就是您的选择.如果您为记录目的进行基准测试,FastPrintf是一个很有前途的库.您可以尝试使用这个声称比内置printf函数快100倍的NuGet包.