Performance Implications of Point-Free style

十年热恋 提交于 2019-12-20 17:34:26

问题


I’m taking my first baby-steps in learning functional programing using F# and I’ve just come across the Forward Pipe (|>) and Forward Composition (>>) operators. At first I thought they were just sugar rather than having an effect on the final running code (though I know piping helps with type inference).

However I came across this SO article: What are advantages and disadvantages of “point free” style in functional programming? Which has two interesting and informative answers (that instead of simplifying things for me opened a whole can of worms surrounding “point-free” or “pointless” style) My take-home from these (and other reading around) is that point-free is a debated area. Like lambas, point-free style can make code easier to understand, or much harder, depending on use. It can help in naming things meaningfully.

But my question concerns a comment on the first answer: AshleyF muses in the answer:

“It seems to me that composition may reduce GC pressure by making it more obvious to the compiler that there is no need to produce intermediate values as in pipelining; helping make the so-called "deforestation" problem more tractable.”

Gasche replies:

“The part about improved compilation is not true at all. In most languages, point-free style will actually decrease performances. Haskell relies heavily on optimizations precisely because it's the only way to make the cost of these things bearable. At best, those combinators are inlined away and you get an equivalent pointful version”

Can anyone expand on the performance implications? (In general and specifically for F#) I had just assumed it was a writing-style thing and the compiler would unstrangle both idioms into equivalent code.


回答1:


This answer is going to be F#-specific. I don't know how the internals of other functional languages work, and the fact that they don't compile to CIL could make a big difference.

I can see three questions here:

  1. What are the performance implications of using |>?
  2. What are the performance implications of using >>?
  3. What is the performance difference between declaring a function with its arguments and without them?

The answers (using examples from the question you linked to):

  1. Is there any difference between x |> sqr |> sum and sum (sqr x)?

    No, there isn't. The compiled CIL is exactly the same (here represented in C#):

    sum.Invoke(sqr.Invoke(x))
    

    (Invoke() is used, because sqr and sum are not CIL methods, they are FSharpFunc, but that's not relevant here.)

  2. Is there any difference between (sqr >> sum) x and sum (sqr x)?

    No, both samples compile to the same CIL as above.

  3. Is there any difference between let sumsqr = sqr >> sum and let sumsqr x = (sqr >> sum) x?

    Yes, the compiled code is different. If you specify the argument, sumsqr is compiled into a normal CLI method. But if you don't specify it, it's compiled as a property of type FSharpFunc with a backing field, whose Invoke() method contains the code.

    But the effect of all is that invoking the point-free version means loading one field (the FSharpFunc), which is not done if you specify the argument. But I think that shouldn't measurably affect performance, except in the most extreme circumstances.



来源:https://stackoverflow.com/questions/11649893/performance-implications-of-point-free-style

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!