Skip to content

Commit 27862f2

Browse files
committed
Add Hashtbl benchmark
1 parent ae733d7 commit 27862f2

File tree

2 files changed

+150
-0
lines changed

2 files changed

+150
-0
lines changed

bench/bench_hashtbl.ml

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
open Multicore_bench
2+
3+
module Int = struct
4+
include Int
5+
6+
let hash = Fun.id
7+
end
8+
9+
module Htbl = Hashtbl.Make (Int)
10+
11+
let run_one_domain ~budgetf ?(n_ops = 400 * Util.iter_factor) ?(n_keys = 1000)
12+
~percent_mem ?(percent_add = (100 - percent_mem + 1) / 2)
13+
?(prepopulate = true) () =
14+
let limit_mem = percent_mem in
15+
let limit_add = percent_mem + percent_add in
16+
17+
assert (0 <= limit_mem && limit_mem <= 100);
18+
assert (limit_mem <= limit_add && limit_add <= 100);
19+
20+
let t = Htbl.create n_keys in
21+
22+
if prepopulate then
23+
for _ = 1 to n_keys do
24+
let value = Random.bits () in
25+
let key = value mod n_keys in
26+
Htbl.add t key value
27+
done;
28+
29+
let n_ops = (100 + percent_mem) * n_ops / 100 in
30+
31+
let n_ops_todo = Atomic.make 0 |> Multicore_magic.copy_as_padded in
32+
33+
let init _ =
34+
Atomic.set n_ops_todo n_ops;
35+
Random.State.make_self_init ()
36+
in
37+
let work _ state =
38+
let rec work () =
39+
let n = Util.alloc n_ops_todo in
40+
if n <> 0 then
41+
let rec loop n =
42+
if 0 < n then
43+
let value = Random.State.bits state in
44+
let op = (value asr 20) mod 100 in
45+
let key = value mod n_keys in
46+
if op < percent_mem then begin
47+
begin
48+
match Htbl.find t key with _ -> () | exception Not_found -> ()
49+
end;
50+
loop (n - 1)
51+
end
52+
else if op < limit_add then begin
53+
Htbl.add t key value;
54+
loop (n - 1)
55+
end
56+
else begin
57+
Htbl.remove t key;
58+
loop (n - 1)
59+
end
60+
else work ()
61+
in
62+
loop n
63+
in
64+
work ()
65+
in
66+
67+
let config = Printf.sprintf "one domain, %d%% reads" percent_mem in
68+
Times.record ~budgetf ~n_domains:1 ~init ~work ()
69+
|> Times.to_thruput_metrics ~n:n_ops ~singular:"operation" ~config
70+
71+
let mutex = Mutex.create ()
72+
73+
let run_one ~budgetf ~n_domains ?(n_ops = 400 * Util.iter_factor)
74+
?(n_keys = 1000) ~percent_mem ?(percent_add = (100 - percent_mem + 1) / 2)
75+
?(prepopulate = true) () =
76+
let limit_mem = percent_mem in
77+
let limit_add = percent_mem + percent_add in
78+
79+
assert (0 <= limit_mem && limit_mem <= 100);
80+
assert (limit_mem <= limit_add && limit_add <= 100);
81+
82+
let t = Htbl.create n_keys in
83+
84+
if prepopulate then
85+
for _ = 1 to n_keys do
86+
let value = Random.bits () in
87+
let key = value mod n_keys in
88+
Htbl.add t key value
89+
done;
90+
91+
let n_ops = (100 + percent_mem) * n_ops / 100 in
92+
93+
let n_ops_todo = Atomic.make 0 |> Multicore_magic.copy_as_padded in
94+
95+
let init _ =
96+
Atomic.set n_ops_todo n_ops;
97+
Random.State.make_self_init ()
98+
in
99+
let work _ state =
100+
let rec work () =
101+
let n = Util.alloc n_ops_todo in
102+
if n <> 0 then
103+
let rec loop n =
104+
if 0 < n then
105+
let value = Random.State.bits state in
106+
let op = (value asr 20) mod 100 in
107+
let key = value mod n_keys in
108+
if op < percent_mem then begin
109+
Mutex.lock mutex;
110+
begin
111+
match Htbl.find t key with _ -> () | exception Not_found -> ()
112+
end;
113+
Mutex.unlock mutex;
114+
loop (n - 1)
115+
end
116+
else if op < limit_add then begin
117+
Mutex.lock mutex;
118+
Htbl.add t key value;
119+
Mutex.unlock mutex;
120+
loop (n - 1)
121+
end
122+
else begin
123+
Mutex.lock mutex;
124+
Htbl.remove t key;
125+
Mutex.unlock mutex;
126+
loop (n - 1)
127+
end
128+
else work ()
129+
in
130+
loop n
131+
in
132+
work ()
133+
in
134+
135+
let config =
136+
Printf.sprintf "%d worker%s, %d%% reads" n_domains
137+
(if n_domains = 1 then "" else "s")
138+
percent_mem
139+
in
140+
Times.record ~budgetf ~n_domains ~init ~work ()
141+
|> Times.to_thruput_metrics ~n:n_ops ~singular:"operation" ~config
142+
143+
let run_suite ~budgetf =
144+
([ 10; 50; 90 ]
145+
|> List.concat_map @@ fun percent_mem ->
146+
run_one_domain ~budgetf ~percent_mem ())
147+
@ (Util.cross [ 10; 50; 90 ] [ 1; 2; 4; 8 ]
148+
|> List.concat_map @@ fun (percent_mem, n_domains) ->
149+
run_one ~budgetf ~n_domains ~percent_mem ())

bench/main.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ let benchmarks =
33
("Ref with [@poll error]", Bench_ref.run_suite);
44
("Ref with Mutex", Bench_ref_mutex.run_suite);
55
("Atomic", Bench_atomic.run_suite);
6+
("Hashtbl", Bench_hashtbl.run_suite);
67
("Queue", Bench_queue.run_suite);
78
("Stack", Bench_stack.run_suite);
89
("Unix", Bench_unix.run_suite);

0 commit comments

Comments
 (0)