Admittedly, I'm not sure if I'm comparing apples to apples or apples to pears right here. But I am especially surprised at the proximity of the difference, where we can expect a weaker difference, if any.
A pipeline can often be expressed as a composition of a function and vice versa , and I would suggest that the compiler knows this too, so I tried a little experiment:
// simplified example of some SB helpers: let inline bcreate() = new StringBuilder(64) let inline bget (sb: StringBuilder) = sb.ToString() let inline appendf fmt (sb: StringBuilder) = Printf.kbprintf (fun () -> sb) sb fmt let inline appends (s: string) (sb: StringBuilder) = sb.Append s let inline appendi (i: int) (sb: StringBuilder) = sb.Append i let inline appendb (b: bool) (sb: StringBuilder) = sb.Append b // test function for composition, putting some garbage data in SB let compose a = (appends "START" >> appendb true >> appendi 10 >> appendi a >> appends "0x" >> appendi 65535 >> appendi 10 >> appends "test" >> appends "END") (bcreate()) // test function for piping, putting the same garbage data in SB let pipe a = bcreate() |> appends "START" |> appendb true |> appendi 10 |> appendi a |> appends "0x" |> appendi 65535 |> appendi 10 |> appends "test" |> appends "END"
Testing this option in FSI (64-bit flag --optimize ):
> for i in 1 .. 500000 do compose 123 |> ignore;; Real: 00:00:00.390, CPU: 00:00:00.390, GC gen0: 62, gen1: 1, gen2: 0 val it : unit = () > for i in 1 .. 500000 do pipe 123 |> ignore;; Real: 00:00:00.249, CPU: 00:00:00.249, GC gen0: 27, gen1: 0, gen2: 0 val it : unit = ()
A slight difference would be understandable, but this is a performance decrease of 1.6% (60%).
I would expect the bulk of the work to happen in StringBuilder , but apparently the overhead of the composition has a pretty big impact.
I understand that in most practical situations this difference will be insignificant, but if you write large formatted text files (for example, log files), as in this case, it affects.
I am using the latest version of F #.
performance function-composition f # piping
Abel
source share