【问题标题】:Performance of sprintf vs String.Format [duplicate]sprintf vs String.Format的性能[重复]
【发布时间】:2013-05-24 19:18:59
【问题描述】:

我正在比较 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# 空间中是否有更好的选择?

【问题讨论】:

  • 既然您已经知道它使用反射,那么您到底在寻找什么?
  • 比较printf source 和StringBuilder.AppendFormat。 printf 做的更多,例如递归集合打印。
  • 只有 %A 使用反射。 %i 将是基本情况。
  • 这符合“为什么 x 比 y 慢得多”的典型问题。有了常见的答案,“x 并不慢,y 只是经过大量优化以提高速度”。 .NET 中的复合字符串格式化当然是这种情况,其中很大一部分以手动调整的 C++ 代码存在于 CLR 中。随之而来的是,如果您需要解决它,请使用分析器来知道。没有的可能性很高,字符串用于 I/O,这已经很慢了。嘿,押韵很好;)

标签: .net string performance f#


【解决方案1】:

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

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

在我错过的 F# 空间中是否有更好的选择?

如果您的目的是构造大字符串,StringWriter 和 StringBuilder 可能是可行的方法。如果您为记录目的进行基准测试,FastPrintf 是一个很有前途的库。你可以试试this NuGet package,它声称比内置的printf 函数快100 倍。

【讨论】:

    猜你喜欢
    • 2012-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-27
    • 2023-03-18
    • 2014-02-28
    • 2013-04-30
    • 2016-03-17
    相关资源
    最近更新 更多