틀림없이 나는 사과와 사과를 사과와 정확하게 비교하고 있는지 확실하지 않습니다. 그러나 나는 차이의 bigness에 대해 특히 놀랍습니다. 차이가있을 경우, 차이가있을 것으로 예상됩니다.F #에서 기능 구성이 배관보다 60 % 더 느린 이유는 무엇입니까?
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 # 최신 버전을 사용하고 있습니다. 내가 생성 된 IL에서 무엇을 말할 수있는 F 번호 내부, 대한 깊은 지식없이
감사합니다. 매우 흥미로운 비교입니다. 서버 GC를 사용하고 일반, 단일 스레드 GC가 있습니까? 나는 FSI를 어떻게 구성 할 지 모르겠습니다. 나는 컴파일 된 버전을 비교해야한다. 적어도 시스템에서 차이점은 무시할 만하다고 생각합니다. – Abel
필자가 언급 한 '--optimize' 이외의 FSI에 특별한 플래그를 사용하지 않습니다. 문제가 발생하면 fsianycpu.exe도 실행 중입니다. – Ringil
@Ringil 나는 람다에 대해 동의하지 않습니다. 예, 최적화되지 않은 코드로 생성됩니다. 그러나 최적화를 사용하면 9 개가 아니라 2 개의 람다 만 볼 수 있습니다. 다른 모든 것은 인라인됩니다. 결론은 컴파일러가 파이핑의 경우보다 인라 인닝을 계산할 때 시간이 더 많이 필요하다는 것입니다. –