【发布时间】:2016-09-06 12:54:29
【问题描述】:
诚然,我不确定我在这里将苹果与苹果或苹果与梨进行比较是否正确。但我对差异的巨大感到特别惊讶,如果有的话,可能会有更小的差异。
管道can often be expressed as function composition and vice versa,我假设编译器也知道这一点,所以我尝试了一个小实验:
// 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"
在 FSI 中测试(启用 64 位,--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 = ()
一个小的差异是可以理解的,但这会导致性能下降 1.6 (60%) 倍。
我实际上希望大部分工作发生在StringBuilder,但显然组合的开销有相当大的影响。
我意识到,在大多数实际情况下,这种差异可以忽略不计,但如果您在这种情况下编写大格式文本文件(如日志文件),则会产生影响。
我使用的是最新版本的 F#。
【问题讨论】:
标签: performance f# piping function-composition