refactor flat_tbl to not store hash

This commit is contained in:
Simon Cruanes 2021-04-03 01:10:49 -04:00
parent edccae0c89
commit 4980d84515
2 changed files with 29 additions and 12 deletions

View file

@ -61,6 +61,10 @@ module type S = sig
val stats : 'a t -> int * int * int * int * int * int val stats : 'a t -> int * int * int * int * int * int
(** Cf Weak.S *) (** Cf Weak.S *)
(**/**)
val _pp_dib : _ t -> string
(**/**)
end end
module Make(H : Hashtbl.HashedType) = struct module Make(H : Hashtbl.HashedType) = struct
@ -74,11 +78,10 @@ module Make(H : Hashtbl.HashedType) = struct
| Used of { | Used of {
k: key; k: key;
mutable v: 'a; mutable v: 'a;
hash: int;
mutable dib: int; (* DIB: distance to initial bucket *) mutable dib: int; (* DIB: distance to initial bucket *)
} }
let max_load = 0.92 let max_load = 0.8
type 'a t = { type 'a t = {
mutable slots: 'a slot array; (* slot for index [i] *) mutable slots: 'a slot array; (* slot for index [i] *)
@ -125,10 +128,10 @@ module Make(H : Hashtbl.HashedType) = struct
match Array.unsafe_get slots j with match Array.unsafe_get slots j with
| Empty -> | Empty ->
Array.unsafe_set slots j (Used {k; v; hash=h; dib}); Array.unsafe_set slots j (Used {k; v; dib});
self.max_dib <- max dib self.max_dib self.max_dib <- max dib self.max_dib
| Used used_j -> | Used used_j ->
if used_j.hash = h && H.equal k used_j.k then ( if H.equal k used_j.k then (
(* same key: replace *) (* same key: replace *)
used_j.v <- v; used_j.v <- v;
used_j.dib <- dib; used_j.dib <- dib;
@ -138,10 +141,10 @@ module Make(H : Hashtbl.HashedType) = struct
(* displace element*) (* displace element*)
let k_j = used_j.k in let k_j = used_j.k in
let v_j = used_j.v in let v_j = used_j.v in
let h_j = used_j.hash in let h_j = H.hash k_j in
let dib_j = used_j.dib in let dib_j = used_j.dib in
Array.unsafe_set slots j (Used {k;v;hash=h;dib}); Array.unsafe_set slots j (Used {k;v;dib});
self.max_dib <- max dib self.max_dib; self.max_dib <- max dib self.max_dib;
insert_rec_ h_j k_j v_j dib_j insert_rec_ h_j k_j v_j dib_j
@ -171,8 +174,9 @@ module Make(H : Hashtbl.HashedType) = struct
Array.iter Array.iter
(fun slot -> match slot with (fun slot -> match slot with
| Empty -> () | Empty -> ()
| Used {k; v; hash; _} -> | Used {k; v; _} ->
insert_ self hash k v) let h = H.hash k in
insert_ self h k v)
old_slots; old_slots;
() ()
@ -188,7 +192,7 @@ module Make(H : Hashtbl.HashedType) = struct
match Array.unsafe_get slots j with match Array.unsafe_get slots j with
| Empty -> None | Empty -> None
| Used used_j -> | Used used_j ->
if used_j.hash = h && H.equal used_j.k k then ( if H.equal used_j.k k then (
Some used_j.v (* found *) Some used_j.v (* found *)
) else if dib >= max_dib then ( ) else if dib >= max_dib then (
None (* no need to go further *) None (* no need to go further *)
@ -201,7 +205,7 @@ module Make(H : Hashtbl.HashedType) = struct
match Array.unsafe_get slots j with match Array.unsafe_get slots j with
| Empty -> None | Empty -> None
| Used used_j -> | Used used_j ->
if used_j.hash = h && H.equal used_j.k k then ( if H.equal used_j.k k then (
Some used_j.v (* found *) Some used_j.v (* found *)
) else if dib >= max_dib then ( ) else if dib >= max_dib then (
None (* no need to go further *) None (* no need to go further *)
@ -214,7 +218,7 @@ module Make(H : Hashtbl.HashedType) = struct
(* try a direct hit first *) (* try a direct hit first *)
begin match Array.unsafe_get slots (addr_ h n 0) with begin match Array.unsafe_get slots (addr_ h n 0) with
| Empty -> None | Empty -> None
| Used {k=k2; v; hash; _} when h = hash && H.equal k k2 -> Some v | Used {k=k2; v; _} when H.equal k k2 -> Some v
| _ -> find_rec_ 1 | _ -> find_rec_ 1
end end
@ -269,7 +273,7 @@ module Make(H : Hashtbl.HashedType) = struct
| Empty -> () | Empty -> ()
| _ when dib > self.max_dib -> () | _ when dib > self.max_dib -> ()
| Used used_j -> | Used used_j ->
if h = used_j.hash && H.equal k used_j.k then ( if H.equal k used_j.k then (
(* found element, remove it *) (* found element, remove it *)
Array.unsafe_set slots j Empty; Array.unsafe_set slots j Empty;
self.size <- self.size - 1; self.size <- self.size - 1;
@ -337,6 +341,15 @@ module Make(H : Hashtbl.HashedType) = struct
(* Statistics on the table *) (* Statistics on the table *)
let stats t = (Array.length t.slots, t.size, t.size, 0, 0, 1) let stats t = (Array.length t.slots, t.size, t.size, 0, 0, 1)
let _pp_dib self =
let buf = Buffer.create 32 in
Array.iter(function
| Empty -> Printf.bprintf buf "_."
| Used {dib;_} -> Printf.bprintf buf "%d." dib)
self.slots;
Printf.bprintf buf "[mdib=%d,size=%d]" self.max_dib self.size;
Buffer.contents buf
end end
(*$inject (*$inject

View file

@ -54,6 +54,10 @@ module type S = sig
val stats : 'a t -> int * int * int * int * int * int val stats : 'a t -> int * int * int * int * int * int
(** Cf Weak.S *) (** Cf Weak.S *)
(**/**)
val _pp_dib : _ t -> string
(**/**)
end end
(** Create a hashtable *) (** Create a hashtable *)