Performance 无点样式的性能含义

Performance 无点样式的性能含义,performance,f#,functional-programming,pointfree,Performance,F#,Functional Programming,Pointfree,我正在学习使用F#进行函数编程的第一步,我刚刚遇到了Forward Pipe(|>)和Forward Composition(>>)操作符。起初我认为它们只是糖,而不是对最终运行的代码产生影响(尽管我知道管道有助于类型推断) 然而,我看到了这篇文章: 这有两个有趣且信息丰富的答案(我没有简化事情,而是打开了一整罐围绕“无点”或“无点”风格的蠕虫),我从这些(以及其他阅读材料)中得到的结论是,无点是一个有争议的领域。像lambas一样,无点样式可以使代码更容易理解,或者更难理解,这取决于使用情况。

我正在学习使用F#进行函数编程的第一步,我刚刚遇到了Forward Pipe(|>)和Forward Composition(>>)操作符。起初我认为它们只是糖,而不是对最终运行的代码产生影响(尽管我知道管道有助于类型推断)

然而,我看到了这篇文章: 这有两个有趣且信息丰富的答案(我没有简化事情,而是打开了一整罐围绕“无点”或“无点”风格的蠕虫),我从这些(以及其他阅读材料)中得到的结论是,无点是一个有争议的领域。像lambas一样,无点样式可以使代码更容易理解,或者更难理解,这取决于使用情况。它有助于有意义地命名事物

但我的问题涉及对第一个答案的评论: 阿什利夫在回答中沉思道:

“在我看来,通过使编译器更清楚地认识到不需要像在流水线中那样生成中间值,组合可以减少GC压力;这有助于使所谓的“毁林”问题更容易处理。”

加什回答说:

“关于改进编译的部分一点也不正确。在大多数语言中,无点风格实际上会降低性能。Haskell严重依赖优化,正是因为这是使这些事情的成本可以承受的唯一方法。充其量,这些组合符是内联的,您可以得到一个等效的有点版本”


有人能详细说明性能影响吗?(一般来说,特别是对于F#)我刚才假设这是一种写作风格,编译器会将这两种习语转换成等价的代码。

这个答案将是F#特有的。我不知道其他函数式语言的内部是如何工作的,而它们不编译成CIL的事实可能会产生很大的不同

我可以在这里看到三个问题:

  • 使用
    |>
    对性能有什么影响
  • 使用
    >
    会对性能产生什么影响
  • 声明带参数的函数和不带参数的函数在性能上有什么区别
  • 答案(使用以下示例):

  • x |>sqr |>sum
    sum(sqrx)
    之间有什么区别吗

    不,没有。编译后的CIL完全相同(这里用C表示):

    Invoke()
    被使用,因为
    sqr
    sum
    不是CIL方法,它们是
    FSharpFunc
    ,但这与此处无关。)

  • (sqr>>sum)x
    sum(sqr x)
    之间有什么区别吗

    否,这两个示例编译为与上面相同的CIL

  • 让sumsqr=sqr>>求和
    让sumsqr x=(sqr>>求和)x
    之间有什么区别吗

    是的,编译的代码是不同的。如果指定参数,
    sumsqr
    将编译为普通CLI方法。但是如果不指定它,它将被编译为类型为
    FSharpFunc
    的属性,并带有一个支持字段,其
    Invoke()
    方法包含代码

    但其效果是调用无点版本意味着加载一个字段(
    FSharpFunc
    ),如果指定参数,则不会执行此操作。但我认为这不应该对性能产生可测量的影响,除非在最极端的情况下


  • 如果有这样或那样的性能差异,我敢肯定在大多数情况下,它将是非常小的。因此,除非您正在编写代码中对性能至关重要的部分,否则您不必担心这一点。顺便说一句,
    (|>)
    与无点编程(它只允许函数的参数在语法上放在函数本身之前)并不是真正相关的,应该是内联的,所以应该不会对性能造成影响。@kvb这是我对|>(我的问题最初甚至更长、更杂乱-我想要求更多关于点自由度的澄清,但我认为我应该为自己多读一点,因为已经有很多了)好的,这就是我希望得到的关于F#specific的答案。你可以使用.NET Reflector来生成上面给出的答案(以及其他场景的答案)。@JonathanLeonard是的,这就是我使用的答案。但是Reflector不再是免费的了,还有像dotPeek或ILSpy这样的免费替代品。这是我喜欢看到的那种经过充分论证和研究的答案。
    sum.Invoke(sqr.Invoke(x))