refactor benchmarks on associative maps

This commit is contained in:
Simon Cruanes 2015-09-05 13:17:11 +02:00
parent 6f388b5d3c
commit 42e360eadd

View file

@ -178,313 +178,203 @@ module Cache = struct
end end
module Tbl = struct module Tbl = struct
module IHashtbl = Hashtbl.Make(struct module type INT_FIND = sig
type t = int type 'a t
let equal i j = i = j val name : string
let hash i = i val init : int -> (int -> 'a) -> 'a t
end) val find : 'a t -> int -> 'a
end
module IPersistentHashtbl = CCPersistentHashtbl.Make(struct (** Signature for mutable int map *)
type t = int module type INT_MUT = sig
let equal i j = i = j type 'a t
let hash i = i val name : string
end) val find : 'a t -> int -> 'a
val create : int -> 'a t
val add : 'a t -> int -> 'a -> unit
val replace : 'a t -> int -> 'a -> unit
end
module IMap = Map.Make(struct module type INT_IMMUT = sig
type t = int type 'a t
let compare i j = i - j val name : string
end) val empty : 'a t
val find : int -> 'a t -> 'a
val add : int -> 'a -> 'a t -> 'a t
end
module ICCHashtbl = CCFlatHashtbl.Make(struct module MUT_OF_IMMUT(T : INT_IMMUT) : INT_MUT with type 'a t = 'a T.t ref = struct
type t = int type 'a t = 'a T.t ref
let equal i j = i = j let name = T.name
let hash i = i let create _ = ref T.empty
end) let find m k = T.find k !m
let add m k v = m := T.add k v !m
let replace = add
end
module IHashTrie = CCHashTrie.Make(struct let hashtbl_make_int =
type t = int let module T = struct let name = "hashtbl.make(int)" include Hashtbl.Make(CCInt) end in
let equal (i:int) j = i=j (module T : INT_MUT)
let hash i = i land max_int
end)
module IHAMT = Hamt.Make(Hamt.StdConfig)(CCInt) let persistent_hashtbl =
let module T = CCPersistentHashtbl.Make(CCInt) in
let module U = struct
type 'a t = 'a T.t ref
let name = "persistent_hashtbl"
let create _ = ref (T.empty ())
let find m k = T.find !m k
let add m k v = m := T.replace !m k v
let replace = add
end in
(module U : INT_MUT)
let phashtbl_add n = let hashtbl =
let h = PHashtbl.create 50 in let module T = struct
for i = n downto 0 do type 'a t = (int, 'a) Hashtbl.t
PHashtbl.add h i i; let name = "hashtbl"
done; let create i = Hashtbl.create i
h let find = Hashtbl.find
let add = Hashtbl.add
let replace = Hashtbl.replace
end in
(module T : INT_MUT)
let hashtbl_add n = let poly_hashtbl =
let h = Hashtbl.create 50 in let module T = struct
for i = n downto 0 do type 'a t = (int, 'a) PHashtbl.t
Hashtbl.add h i i; let name = "phashtbl"
done; let create i = PHashtbl.create ~hash:CCInt.hash ~eq:CCInt.equal i
h let find = PHashtbl.find
let add = PHashtbl.add
let replace = PHashtbl.replace
end in
(module T : INT_MUT)
let ihashtbl_add n = let map =
let h = IHashtbl.create 50 in let module T = struct let name = "map" include Map.Make(CCInt) end in
for i = n downto 0 do let module U = MUT_OF_IMMUT(T) in
IHashtbl.add h i i; (module U : INT_MUT)
done;
h
let ipersistenthashtbl_add n = let flat_hashtbl =
let h = ref (IPersistentHashtbl.create 32) in let module T = CCFlatHashtbl.Make(CCInt) in
for i = n downto 0 do let module U = struct
h := IPersistentHashtbl.replace !h i i; type 'a t = 'a T.t
done; let name = "ccflat_hashtbl"
!h let create = T.create
let find = T.find_exn
let add = T.add
let replace = T.add
end in
(module U : INT_MUT)
let imap_add n = let hashtrie =
let h = ref IMap.empty in let module T = struct
for i = n downto 0 do let name = "cchashtrie"
h := IMap.add i i !h; include CCHashTrie.Make(CCInt)
done; let find = get_exn
!h end in
let module U = MUT_OF_IMMUT(T) in
(module U : INT_MUT)
let intmap_add n = let hamt =
let h = ref CCIntMap.empty in let module T = struct
for i = n downto 0 do let name = "hamt"
h := CCIntMap.add i i !h; include Hamt.Make(Hamt.StdConfig)(CCInt)
done; let find = find_exn
!h end in
let module U = MUT_OF_IMMUT(T) in
(module U : INT_MUT)
let hashtrie_add n = let modules =
let h = ref IHashTrie.empty in [ hashtbl_make_int
for i = n downto 0 do ; hashtbl
h := IHashTrie.add i i !h; ; persistent_hashtbl
done; ; poly_hashtbl
!h ; map
; flat_hashtbl
let hamt_add n = ; hashtrie
let h = ref IHAMT.empty in ; hamt
for i = n downto 0 do
h := IHAMT.add i i !h;
done;
!h
let icchashtbl_add n =
let h = ICCHashtbl.create 50 in
for i = n downto 0 do
ICCHashtbl.add h i i;
done;
h
let bench_maps1 n =
B.throughputN 3 ~repeat
["phashtbl_add", (fun n -> ignore (phashtbl_add n)), n;
"hashtbl_add", (fun n -> ignore (hashtbl_add n)), n;
"ihashtbl_add", (fun n -> ignore (ihashtbl_add n)), n;
"ipersistenthashtbl_add", (fun n -> ignore (ipersistenthashtbl_add n)), n;
"imap_add", (fun n -> ignore (imap_add n)), n;
"intmap_add", (fun n -> ignore (intmap_add n)), n;
"ccflathashtbl_add", (fun n -> ignore (icchashtbl_add n)), n;
"cchashtrie_add", (fun n -> ignore (hashtrie_add n)), n;
"hamt_add", (fun n -> ignore (hamt_add n)), n;
] ]
let phashtbl_replace n = let bench_add n =
let h = PHashtbl.create 50 in let make (module T : INT_MUT) =
let run() =
let t = T.create 50 in
for i = n downto 0 do
T.add t i i;
done
in
T.name, run, ()
in
B.throughputN 3 ~repeat (List.map make modules)
let bench_replace n =
let make (module T : INT_MUT) =
let run() =
let t = T.create 50 in
for i = 0 to n do for i = 0 to n do
PHashtbl.replace h i i; T.replace t i i;
done; done;
for i = n downto 0 do for i = n downto 0 do
PHashtbl.replace h i i; T.replace t i i;
done; done;
h ()
in
T.name, run, ()
in
B.throughputN 3 ~repeat (List.map make modules)
let hashtbl_replace n = let find_of_mut (module T : INT_MUT) : (module INT_FIND) =
let h = Hashtbl.create 50 in let module U = struct
for i = 0 to n do include T
Hashtbl.replace h i i; let init n f =
done; let t = T.create n in
for i = n downto 0 do for i=0 to n-1 do T.add t i (f i) done;
Hashtbl.replace h i i; t
done; end in
h (module U)
let ihashtbl_replace n = let array =
let h = IHashtbl.create 50 in let module T = struct
for i = 0 to n do type 'a t = 'a array
IHashtbl.replace h i i; let name = "array"
done; let init = Array.init
for i = n downto 0 do let find a i = a.(i)
IHashtbl.replace h i i; end in
done; (module T : INT_FIND)
h
let ipersistenthashtbl_replace n = let persistent_array =
let h = ref (IPersistentHashtbl.create 32) in let module A = CCPersistentArray in
for i = 0 to n do let module T = struct
h := IPersistentHashtbl.replace !h i i; type 'a t = 'a A.t
done; let name = "persistent_array"
for i = n downto 0 do let init = A.init
h := IPersistentHashtbl.replace !h i i; let find = A.get
done; end in
!h (module T : INT_FIND)
let imap_replace n = let modules' =
let h = ref IMap.empty in [ array
for i = 0 to n do ; persistent_array ] @
h := IMap.add i i !h; List.map find_of_mut modules
done;
for i = n downto 0 do
h := IMap.add i i !h;
done;
!h
let intmap_replace n = let bench_find n =
let h = ref CCIntMap.empty in let make (module T : INT_FIND) =
for i = 0 to n do let m = T.init n (fun i -> i) in
h := CCIntMap.add i i !h; let run() =
done;
for i = n downto 0 do
h := CCIntMap.add i i !h;
done;
!h
let hashtrie_replace n =
let h = ref IHashTrie.empty in
for i = 0 to n do
h := IHashTrie.add i i !h;
done;
for i = n downto 0 do
h := IHashTrie.add i i !h;
done;
!h
let hamt_replace n =
let h = ref IHAMT.empty in
for i = 0 to n do
h := IHAMT.add i i !h;
done;
for i = n downto 0 do
h := IHAMT.add i i !h;
done;
!h
let icchashtbl_replace n =
let h = ICCHashtbl.create 50 in
for i = 0 to n do
ICCHashtbl.add h i i;
done;
for i = n downto 0 do
ICCHashtbl.add h i i;
done;
h
let bench_maps2 n =
B.throughputN 3 ~repeat
["phashtbl_replace", (fun n -> ignore (phashtbl_replace n)), n;
"hashtbl_replace", (fun n -> ignore (hashtbl_replace n)), n;
"ihashtbl_replace", (fun n -> ignore (ihashtbl_replace n)), n;
"ipersistenthashtbl_replace", (fun n -> ignore (ipersistenthashtbl_replace n)), n;
"imap_replace", (fun n -> ignore (imap_replace n)), n;
"intmap_replace", (fun n -> ignore (intmap_replace n)), n;
"ccflathashtbl_replace", (fun n -> ignore (icchashtbl_replace n)), n;
"hashtrie_replace", (fun n -> ignore (hashtrie_replace n)), n;
"hamt_replace", (fun n -> ignore (hamt_replace n)), n;
]
let phashtbl_find h =
fun n ->
for i = 0 to n-1 do for i = 0 to n-1 do
ignore (PHashtbl.find h i); ignore (T.find m i)
done done
in
let hashtbl_find h = T.name, run, ()
fun n -> in
for i = 0 to n-1 do Benchmark.throughputN 3 ~repeat (List.map make modules')
ignore (Hashtbl.find h i);
done
let ihashtbl_find h =
fun n ->
for i = 0 to n-1 do
ignore (IHashtbl.find h i);
done
let ipersistenthashtbl_find h =
fun n ->
for i = 0 to n-1 do
ignore (IPersistentHashtbl.find h i);
done
let array_find a =
fun n ->
for i = 0 to n-1 do
ignore (Array.get a i);
done
let persistent_array_find a =
fun n ->
for i = 0 to n-1 do
ignore (CCPersistentArray.get a i);
done
let imap_find m =
fun n ->
for i = 0 to n-1 do
ignore (IMap.find i m);
done
let intmap_find m =
fun n ->
for i = 0 to n-1 do
ignore (CCIntMap.find i m);
done
let hashtrie_find m =
fun n ->
for i = 0 to n-1 do
ignore (IHashTrie.get_exn i m);
done
let hamt_find m =
fun n ->
for i = 0 to n-1 do
ignore (IHAMT.find_exn i m);
done
let icchashtbl_find m =
fun n ->
for i = 0 to n-1 do
ignore (ICCHashtbl.get_exn i m);
done
let bench_maps3 n =
let h = phashtbl_add n in
let h' = hashtbl_add n in
let h'' = ihashtbl_add n in
let h''''' = ipersistenthashtbl_add n in
let a = Array.init n string_of_int in
let pa = CCPersistentArray.init n string_of_int in
let m = imap_add n in
let m' = intmap_add n in
let h'''''' = icchashtbl_add n in
let ht = hashtrie_add n in
let hamt = hamt_add n in
B.throughputN 3 ~repeat [
"phashtbl_find", (fun () -> phashtbl_find h n), ();
"hashtbl_find", (fun () -> hashtbl_find h' n), ();
"ihashtbl_find", (fun () -> ihashtbl_find h'' n), ();
"ipersistenthashtbl_find", (fun () -> ipersistenthashtbl_find h''''' n), ();
"array_find", (fun () -> array_find a n), ();
"persistent_array_find", (fun () -> persistent_array_find pa n), ();
"imap_find", (fun () -> imap_find m n), ();
"intmap_find", (fun () -> intmap_find m' n), ();
"ccflathashtbl_find", (fun () -> icchashtbl_find h'''''' n), ();
"hashtrie_find", (fun () -> hashtrie_find ht n), ();
"hamt_find", (fun () -> hamt_find hamt n), ();
]
let () = B.Tree.register ( let () = B.Tree.register (
"tbl" @>>> "tbl" @>>>
[ "add" @>> app_ints bench_maps1 [10; 100; 1_000; 10_000;] [ "add" @>> app_ints bench_add [10; 100; 1_000; 10_000;]
; "replace" @>> app_ints bench_maps2 [10; 100; 1_000; 10_000] ; "replace" @>> app_ints bench_replace [10; 100; 1_000; 10_000]
; "find" @>> app_ints bench_maps3 [10; 20; 100; 1_000; 10_000] ; "find" @>> app_ints bench_find [10; 20; 100; 1_000; 10_000]
]) ])
end end