Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

benchmark various implementations of Bench.to_seq discussed in #1006 #1010

Merged
merged 1 commit into from
Jan 31, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ BENCH_TARGETS += benchsuite/lines_of.native
BENCH_TARGETS += benchsuite/bitset.native
BENCH_TARGETS += benchsuite/bench_map.native
BENCH_TARGETS += benchsuite/bench_nreplace.native
BENCH_TARGETS += benchsuite/bench_set_to_seq.native
TEST_TARGET = test-byte

ifeq ($(BATTERIES_NATIVE_SHLIB), yes)
Expand Down
80 changes: 80 additions & 0 deletions benchsuite/bench_set_to_seq.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
(* cd .. && ocamlbuild -use-ocamlfind benchsuite/bench_set_to_seq.native && _build/benchsuite/bench_set_to_seq.native *)

(* The purpose of this test is to compare different implementation of
BatSet.to_seq. *)

(* the type BatSet.t is abstract,
we break the abstraction boundary locally to implement our versions outside the module. *)
type 'a set =
| Empty
| Node of 'a set * 'a * 'a set * int
external hide : 'a set -> 'a BatSet.t = "%identity"
external reveal : 'a BatSet.t -> 'a set = "%identity"


module TooStrict = struct
let rec to_seq m =
match m with
| Empty -> BatSeq.nil
| Node(l, v, r, _) ->
BatSeq.append (to_seq l) (fun () -> BatSeq.Cons (v, to_seq r))

let to_seq s = to_seq (reveal s)
end

module Simple = struct
let rec to_seq m =
fun () ->
match m with
| Empty -> BatSeq.Nil
| Node(l, v, r, _) ->
BatSeq.append (to_seq l) (fun () -> BatSeq.Cons (v, to_seq r)) ()

let to_seq s = to_seq (reveal s)
end

module Enumeration = struct
type 'a iter = E | C of 'a * 'a set * 'a iter

let rec cons_iter s t = match s with
| Empty -> t
| Node (l, e, r, _) -> cons_iter l (C (e, r, t))

let to_seq s =
let rec to_seq iter () =
match iter with
| E -> BatSeq.Nil
| C (e, r, t) ->
BatSeq.Cons (e, to_seq (cons_iter r t))
in
to_seq (cons_iter s E)

let to_seq s = to_seq (reveal s)
end

let test_input =
let s = ref BatSet.empty in
for i = 0 to 9999 do
s := BatSet.add i !s;
done;
!s

let test to_seq =
test_input
|> to_seq
|> BatSeq.length

let () =
assert (test TooStrict.to_seq = test BatSet.to_seq);
assert (test Simple.to_seq = test BatSet.to_seq);
assert (test Enumeration.to_seq = test BatSet.to_seq);
()

let () =
let repeat f n = for i = 1 to n do ignore (f ()) done in
Bench.bench_n [
"too strict", repeat (fun () -> test TooStrict.to_seq);
"simple", repeat (fun () -> test Simple.to_seq);
"enumeration", repeat (fun () -> test Enumeration.to_seq);
"batseq", repeat (fun () -> test BatSet.to_seq);
] |> Bench.run_outputs