C#编译器足够聪明,可以将+
运算符的字符串连接优化为String.Concat
调用。
如下代码:
var a = "one";
var b = "two";
var c = "three";
var d = "four";
var x = a + b + c + d;
被编译成这个IL:
IL_0000: ldstr "one"
IL_0005: stloc.0 // a
IL_0006: ldstr "two"
IL_000B: stloc.1 // b
IL_000C: ldstr "three"
IL_0011: stloc.2 // c
IL_0012: ldstr "four"
IL_0017: stloc.3 // d
IL_0018: ldloc.0 // a
IL_0019: ldloc.1 // b
IL_001A: ldloc.2 // c
IL_001B: ldloc.3 // d
IL_001C: call System.String.Concat
编译器找出了正确的
String.Concat
重载,并使用了4个参数。F#编译器不会这样做。而是将每个
+
编译成一个单独的String.Concat
调用:IL_0005: ldstr "one"
IL_000A: ldstr "two"
IL_000F: call System.String.Concat
IL_0014: ldstr "three"
IL_0019: call System.String.Concat
IL_001E: ldstr "four"
IL_0023: call System.String.Concat
显然,这是因为该特定优化未在F#编译器中实现。
问题是为什么:在技术上很难做到还是还有其他原因?
字符串连接是一个相当常见的操作,尽管我意识到编译代码的性能不是最优先考虑的事情,但我认为这种优化在许多情况下会很有用。
最佳答案
我认为优化没有什么困难-我认为未实现优化的主要原因是它特定于字符串连接,并且不适用于更广泛的范围。但是,听起来像是使用F# open source release会是一个有趣的项目!
也就是说,即使是上面完成的C#优化也不是那么聪明。没有理由为什么编译器不应该在它们为常量并产生时直接将它们直接连接起来:
IL_0000: ldstr "onetwothreefour"
换句话说,在添加通常有用的内容和添加越来越多的特殊情况之间总是要权衡取舍-C#编译器显然还有更多与字符串连接有关的特殊情况...
关于f# - F#编译器中的字符串串联优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21529651/