Performance 无点样式的性能含义
我正在学习使用F#进行函数编程的第一步,我刚刚遇到了Forward Pipe(|>)和Forward Composition(>>)操作符。起初我认为它们只是糖,而不是对最终运行的代码产生影响(尽管我知道管道有助于类型推断) 然而,我看到了这篇文章: 这有两个有趣且信息丰富的答案(我没有简化事情,而是打开了一整罐围绕“无点”或“无点”风格的蠕虫),我从这些(以及其他阅读材料)中得到的结论是,无点是一个有争议的领域。像lambas一样,无点样式可以使代码更容易理解,或者更难理解,这取决于使用情况。它有助于有意义地命名事物 但我的问题涉及对第一个答案的评论: 阿什利夫在回答中沉思道: “在我看来,通过使编译器更清楚地认识到不需要像在流水线中那样生成中间值,组合可以减少GC压力;这有助于使所谓的“毁林”问题更容易处理。” 加什回答说: “关于改进编译的部分一点也不正确。在大多数语言中,无点风格实际上会降低性能。Haskell严重依赖优化,正是因为这是使这些事情的成本可以承受的唯一方法。充其量,这些组合符是内联的,您可以得到一个等效的有点版本”Performance 无点样式的性能含义,performance,f#,functional-programming,pointfree,Performance,F#,Functional Programming,Pointfree,我正在学习使用F#进行函数编程的第一步,我刚刚遇到了Forward Pipe(|>)和Forward Composition(>>)操作符。起初我认为它们只是糖,而不是对最终运行的代码产生影响(尽管我知道管道有助于类型推断) 然而,我看到了这篇文章: 这有两个有趣且信息丰富的答案(我没有简化事情,而是打开了一整罐围绕“无点”或“无点”风格的蠕虫),我从这些(以及其他阅读材料)中得到的结论是,无点是一个有争议的领域。像lambas一样,无点样式可以使代码更容易理解,或者更难理解,这取决于使用情况。
有人能详细说明性能影响吗?(一般来说,特别是对于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))