mirror of
https://github.com/c-cube/ocaml-containers.git
synced 2025-12-06 03:05:28 -05:00
refactor benchmarks on associative maps
This commit is contained in:
parent
6f388b5d3c
commit
42e360eadd
1 changed files with 181 additions and 291 deletions
|
|
@ -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 h = PHashtbl.create 50 in
|
|
||||||
for i = 0 to n do
|
|
||||||
PHashtbl.replace h i i;
|
|
||||||
done;
|
|
||||||
for i = n downto 0 do
|
|
||||||
PHashtbl.replace h i i;
|
|
||||||
done;
|
|
||||||
h
|
|
||||||
|
|
||||||
let hashtbl_replace n =
|
|
||||||
let h = Hashtbl.create 50 in
|
|
||||||
for i = 0 to n do
|
|
||||||
Hashtbl.replace h i i;
|
|
||||||
done;
|
|
||||||
for i = n downto 0 do
|
|
||||||
Hashtbl.replace h i i;
|
|
||||||
done;
|
|
||||||
h
|
|
||||||
|
|
||||||
let ihashtbl_replace n =
|
|
||||||
let h = IHashtbl.create 50 in
|
|
||||||
for i = 0 to n do
|
|
||||||
IHashtbl.replace h i i;
|
|
||||||
done;
|
|
||||||
for i = n downto 0 do
|
|
||||||
IHashtbl.replace h i i;
|
|
||||||
done;
|
|
||||||
h
|
|
||||||
|
|
||||||
let ipersistenthashtbl_replace n =
|
|
||||||
let h = ref (IPersistentHashtbl.create 32) in
|
|
||||||
for i = 0 to n do
|
|
||||||
h := IPersistentHashtbl.replace !h i i;
|
|
||||||
done;
|
|
||||||
for i = n downto 0 do
|
|
||||||
h := IPersistentHashtbl.replace !h i i;
|
|
||||||
done;
|
|
||||||
!h
|
|
||||||
|
|
||||||
let imap_replace n =
|
|
||||||
let h = ref IMap.empty in
|
|
||||||
for i = 0 to n do
|
|
||||||
h := IMap.add i i !h;
|
|
||||||
done;
|
|
||||||
for i = n downto 0 do
|
|
||||||
h := IMap.add i i !h;
|
|
||||||
done;
|
|
||||||
!h
|
|
||||||
|
|
||||||
let intmap_replace n =
|
|
||||||
let h = ref CCIntMap.empty in
|
|
||||||
for i = 0 to n do
|
|
||||||
h := CCIntMap.add i i !h;
|
|
||||||
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
|
|
||||||
ignore (PHashtbl.find h i);
|
|
||||||
done
|
|
||||||
|
|
||||||
let hashtbl_find h =
|
|
||||||
fun n ->
|
|
||||||
for i = 0 to n-1 do
|
|
||||||
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 bench_add n =
|
||||||
|
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
|
||||||
|
T.replace t i i;
|
||||||
|
done;
|
||||||
|
for i = n downto 0 do
|
||||||
|
T.replace t i i;
|
||||||
|
done;
|
||||||
|
()
|
||||||
|
in
|
||||||
|
T.name, run, ()
|
||||||
|
in
|
||||||
|
B.throughputN 3 ~repeat (List.map make modules)
|
||||||
|
|
||||||
|
let find_of_mut (module T : INT_MUT) : (module INT_FIND) =
|
||||||
|
let module U = struct
|
||||||
|
include T
|
||||||
|
let init n f =
|
||||||
|
let t = T.create n in
|
||||||
|
for i=0 to n-1 do T.add t i (f i) done;
|
||||||
|
t
|
||||||
|
end in
|
||||||
|
(module U)
|
||||||
|
|
||||||
|
let array =
|
||||||
|
let module T = struct
|
||||||
|
type 'a t = 'a array
|
||||||
|
let name = "array"
|
||||||
|
let init = Array.init
|
||||||
|
let find a i = a.(i)
|
||||||
|
end in
|
||||||
|
(module T : INT_FIND)
|
||||||
|
|
||||||
|
let persistent_array =
|
||||||
|
let module A = CCPersistentArray in
|
||||||
|
let module T = struct
|
||||||
|
type 'a t = 'a A.t
|
||||||
|
let name = "persistent_array"
|
||||||
|
let init = A.init
|
||||||
|
let find = A.get
|
||||||
|
end in
|
||||||
|
(module T : INT_FIND)
|
||||||
|
|
||||||
|
let modules' =
|
||||||
|
[ array
|
||||||
|
; persistent_array ] @
|
||||||
|
List.map find_of_mut modules
|
||||||
|
|
||||||
|
let bench_find n =
|
||||||
|
let make (module T : INT_FIND) =
|
||||||
|
let m = T.init n (fun i -> i) in
|
||||||
|
let run() =
|
||||||
|
for i = 0 to n-1 do
|
||||||
|
ignore (T.find m i)
|
||||||
|
done
|
||||||
|
in
|
||||||
|
T.name, run, ()
|
||||||
|
in
|
||||||
|
Benchmark.throughputN 3 ~repeat (List.map make modules')
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue