f# - F#编译器中的字符串串联优化

标签 f#

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/

相关文章:

F# 静态成员

performance - 在 F# 中有效地投影列表列表

c# - F# 适用于已经将函数委托(delegate)作为参数的 C# 程序员

f# - 存在同名属性时如何调用扩展方法?

webpack - 如何使用 Fable-Elmish 添加 img 标签

f# - 将 Enum 转换为基础类型

azure - 如何部署 F# Azure WebJob?

f#:使用 "match/with" block ,不含 "with"

parameters - F# 设置带有参数的 SQLCommand 的最佳方法

f# - 使用 F# Struct 和 Explicit LayoutKind 创建标记联合