Skip to content

Instantly share code, notes, and snippets.

@c-cube
Last active April 21, 2016 12:52
Show Gist options
  • Save c-cube/89569c3a3dc2da72bdc8847ac8c6a3ae to your computer and use it in GitHub Desktop.
Save c-cube/89569c3a3dc2da72bdc8847ac8c6a3ae to your computer and use it in GitHub Desktop.
small benchmark (requires: gen, sequence, benchmark)
module G = struct
type 'a t = unit -> 'a option
let (--) i j =
let r = ref i in
fun () ->
if !r > j then None
else (let x = !r in incr r; Some x)
let map f g =
fun () -> match g() with
| None -> None
| Some x -> Some (f x)
let rec filter f g () = match g() with
| None -> None
| Some x when f x -> Some x
| Some _ -> filter f g ()
type 'a state =
| Start
| Cur of 'a
| Stop
let flat_map f g =
let state = ref Start in
let rec aux () = match !state with
| Start -> next_gen(); aux ()
| Stop -> None
| Cur g' ->
match g'() with
| None -> next_gen(); aux ()
| Some _ as res -> res
and next_gen() = match g() with
| None -> state := Stop
| Some x -> state := Cur (f x)
| exception e -> state := Stop; raise e
in
aux
let rec fold f acc g = match g () with
| None -> acc
| Some x -> fold f (f acc x) g
end
let f_gen () =
let open Gen in
1 -- 100_000
|> map (fun x -> x+1)
|> filter (fun x -> x mod 2 = 0)
|> flat_map (fun x -> x -- (x+30))
|> fold (+) 0
let f_gen_noptim () =
let open Gen in
1 -- 100_000
|> Sys.opaque_identity map (fun x -> x+1)
|> Sys.opaque_identity filter (fun x -> x mod 2 = 0)
|> Sys.opaque_identity flat_map (fun x -> x -- (x+30))
|> Sys.opaque_identity fold (+) 0
let f_g () =
let open G in
1 -- 100_000
|> map (fun x -> x+1)
|> filter (fun x -> x mod 2 = 0)
|> flat_map (fun x -> x -- (x+30))
|> fold (+) 0
let f_seq () =
let open Sequence in
1 -- 100_000
|> map (fun x -> x+1)
|> filter (fun x -> x mod 2 = 0)
|> flat_map (fun x -> x -- (x+30))
|> fold (+) 0
let () =
assert (f_gen_noptim () = f_gen());
assert (f_g () = f_gen());
assert (f_seq () = f_gen());
()
let () =
let res =
(Sys.opaque_identity Benchmark.throughputN) ~repeat:2 3
[ "gen", Sys.opaque_identity f_gen, ()
; "gen_no_optim", Sys.opaque_identity f_gen_noptim, ()
; "g", Sys.opaque_identity f_g, ()
; "sequence", Sys.opaque_identity f_seq, ()
]
in
Benchmark.tabulate res
(* ocamlfind opt -O3 -package gen -package sequence -package benchmark -linkpkg -unbox-closures -inline-call-cost 200 bench.ml -o bench *)
(*
Throughputs for "gen", "gen_no_optim", "g", "sequence" each running 2 times for at least 3 CPU seconds:
gen: 3.14 WALL ( 3.13 usr + 0.00 sys = 3.13 CPU) @ 126.84/s (n=397)
3.14 WALL ( 3.13 usr + 0.00 sys = 3.13 CPU) @ 126.84/s (n=397)
gen_no_optim: 3.17 WALL ( 3.16 usr + 0.00 sys = 3.16 CPU) @ 85.67/s (n=271)
3.17 WALL ( 3.16 usr + 0.00 sys = 3.16 CPU) @ 85.67/s (n=271)
g: 3.18 WALL ( 3.18 usr + 0.00 sys = 3.18 CPU) @ 140.57/s (n=447)
3.18 WALL ( 3.17 usr + 0.01 sys = 3.18 CPU) @ 140.71/s (n=447)
sequence: 3.19 WALL ( 3.18 usr + 0.01 sys = 3.18 CPU) @ 784.08/s (n=2496)
3.19 WALL ( 3.18 usr + 0.00 sys = 3.19 CPU) @ 783.26/s (n=2496)
Rate gen_no_optim gen g sequence
gen_no_optim 85.7+-0.0/s -- -32% -39% -89%
gen 127+- 0/s 48% -- -10% -84%
g 141+- 0/s 64% 11% -- -82%
sequence 784+- 0/s 815% 518% 457% --
*)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment