Skip to content

Commit b1b3ad6

Browse files
committed
Avoid call indirection in Atomic and Ref benchmarks
1 parent 9b9f043 commit b1b3ad6

File tree

2 files changed

+166
-88
lines changed

2 files changed

+166
-88
lines changed

bench/bench_atomic.ml

Lines changed: 83 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -10,62 +10,101 @@ module Atomic = struct
1010
modify ~backoff:(Backoff.once backoff) x f
1111
end
1212

13-
type t = Op : string * int * 'a * ('a Atomic.t -> _) * ('a Atomic.t -> _) -> t
13+
type _ op =
14+
| Get : int op
15+
| Incr : int op
16+
| Push_and_pop : int list op
17+
| Cas_int : int op
18+
| Xchg_int : int op
19+
| Swap : (int * int) op
20+
21+
let run_one (type a) ~budgetf ?(n_iter = 500 * Util.iter_factor) (op : a op) =
22+
let name, extra, (value : a) =
23+
match op with
24+
| Get -> ("get", 10, 42)
25+
| Incr -> ("incr", 1, 0)
26+
| Push_and_pop -> ("push & pop", 2, [])
27+
| Cas_int -> ("cas int", 1, 0)
28+
| Xchg_int -> ("xchg int", 1, 0)
29+
| Swap -> ("swap", 1, (4, 2))
30+
in
1431

15-
let run_one ~budgetf ?(n_iter = 500 * Util.iter_factor)
16-
(Op (name, extra, value, op1, op2)) =
1732
let n_iter = n_iter * extra in
1833

1934
let loc = Atomic.make value in
2035

2136
let init _ = () in
2237
let work _ () =
23-
let rec loop i =
24-
if i > 0 then begin
25-
op1 loc |> ignore;
26-
op2 loc |> ignore;
27-
op1 loc |> ignore;
28-
op2 loc |> ignore;
29-
op1 loc |> ignore;
30-
op2 loc |> ignore;
31-
op1 loc |> ignore;
32-
op2 loc |> ignore;
33-
op1 loc |> ignore;
34-
op2 loc |> ignore;
35-
op1 loc |> ignore;
36-
op2 loc |> ignore;
37-
op1 loc |> ignore;
38-
op2 loc |> ignore;
39-
op1 loc |> ignore;
40-
op2 loc |> ignore;
41-
op1 loc |> ignore;
42-
op2 loc |> ignore;
43-
op1 loc |> ignore;
44-
op2 loc |> ignore;
45-
loop (i - (2 * 10))
46-
end
47-
in
48-
loop n_iter
38+
match op with
39+
| Get ->
40+
let rec loop i =
41+
if i > 0 then begin
42+
Sys.opaque_identity (Atomic.get loc) |> ignore;
43+
Sys.opaque_identity (Atomic.get loc) |> ignore;
44+
loop (i - 2)
45+
end
46+
in
47+
loop n_iter
48+
| Incr ->
49+
let rec loop i =
50+
if i > 0 then begin
51+
Atomic.incr loc;
52+
Atomic.incr loc;
53+
loop (i - 2)
54+
end
55+
in
56+
loop n_iter
57+
| Push_and_pop ->
58+
let push x = Atomic.modify x (fun xs -> 101 :: xs)
59+
and pop x = Atomic.modify x (function [] -> [] | _ :: xs -> xs) in
60+
let rec loop i =
61+
if i > 0 then begin
62+
push loc;
63+
pop loc |> ignore;
64+
loop (i - 2)
65+
end
66+
in
67+
loop n_iter
68+
| Cas_int ->
69+
let rec loop i =
70+
if i > 0 then begin
71+
Atomic.compare_and_set loc 0 1 |> ignore;
72+
Atomic.compare_and_set loc 1 0 |> ignore;
73+
loop (i - 2)
74+
end
75+
in
76+
loop n_iter
77+
| Xchg_int ->
78+
let rec loop i =
79+
if i > 0 then begin
80+
Atomic.exchange loc 1 |> ignore;
81+
Atomic.exchange loc 0 |> ignore;
82+
loop (i - 2)
83+
end
84+
in
85+
loop n_iter
86+
| Swap ->
87+
let swap x = Atomic.modify x (fun (x, y) -> (y, x)) in
88+
let rec loop i =
89+
if i > 0 then begin
90+
swap loc;
91+
swap loc;
92+
loop (i - 2)
93+
end
94+
in
95+
loop n_iter
4996
in
5097

5198
Times.record ~budgetf ~n_domains:1 ~init ~work ()
5299
|> Times.to_thruput_metrics ~n:n_iter ~singular:"op" ~config:name
53100

54101
let run_suite ~budgetf =
55102
[
56-
(let get x = Atomic.get x in
57-
Op ("get", 10, 42, get, get));
58-
(let incr x = Atomic.incr x in
59-
Op ("incr", 1, 0, incr, incr));
60-
(let push x = Atomic.modify x (fun xs -> 101 :: xs)
61-
and pop x = Atomic.modify x (function [] -> [] | _ :: xs -> xs) in
62-
Op ("push & pop", 2, [], push, pop));
63-
(let cas01 x = Atomic.compare_and_set x 0 1
64-
and cas10 x = Atomic.compare_and_set x 1 0 in
65-
Op ("cas int", 1, 0, cas01, cas10));
66-
(let xchg1 x = Atomic.exchange x 1 and xchg0 x = Atomic.exchange x 0 in
67-
Op ("xchg int", 1, 0, xchg1, xchg0));
68-
(let swap x = Atomic.modify x (fun (x, y) -> (y, x)) in
69-
Op ("swap", 2, (4, 2), swap, swap));
103+
run_one ~budgetf Get;
104+
run_one ~budgetf Incr;
105+
run_one ~budgetf Push_and_pop;
106+
run_one ~budgetf Cas_int;
107+
run_one ~budgetf Xchg_int;
108+
run_one ~budgetf Swap;
70109
]
71-
|> List.concat_map @@ run_one ~budgetf
110+
|> List.concat

bench/bench_ref.ml

Lines changed: 83 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -26,62 +26,101 @@ module Ref = struct
2626
modify ~backoff:(Backoff.once backoff) x f
2727
end
2828

29-
type t = Op : string * int * 'a * ('a Ref.t -> _) * ('a Ref.t -> _) -> t
29+
type _ op =
30+
| Get : int op
31+
| Incr : int op
32+
| Push_and_pop : int list op
33+
| Cas_int : int op
34+
| Xchg_int : int op
35+
| Swap : (int * int) op
36+
37+
let run_one (type a) ~budgetf ?(n_iter = 500 * Util.iter_factor) (op : a op) =
38+
let name, extra, (value : a) =
39+
match op with
40+
| Get -> ("get", 10, 42)
41+
| Incr -> ("incr", 1, 0)
42+
| Push_and_pop -> ("push & pop", 2, [])
43+
| Cas_int -> ("cas int", 1, 0)
44+
| Xchg_int -> ("xchg int", 1, 0)
45+
| Swap -> ("swap", 1, (4, 2))
46+
in
3047

31-
let run_one ~budgetf ?(n_iter = 500 * Util.iter_factor)
32-
(Op (name, extra, value, op1, op2)) =
3348
let n_iter = n_iter * extra in
3449

3550
let loc = Ref.make value in
3651

3752
let init _ = () in
3853
let work _ () =
39-
let rec loop i =
40-
if i > 0 then begin
41-
op1 loc |> ignore;
42-
op2 loc |> ignore;
43-
op1 loc |> ignore;
44-
op2 loc |> ignore;
45-
op1 loc |> ignore;
46-
op2 loc |> ignore;
47-
op1 loc |> ignore;
48-
op2 loc |> ignore;
49-
op1 loc |> ignore;
50-
op2 loc |> ignore;
51-
op1 loc |> ignore;
52-
op2 loc |> ignore;
53-
op1 loc |> ignore;
54-
op2 loc |> ignore;
55-
op1 loc |> ignore;
56-
op2 loc |> ignore;
57-
op1 loc |> ignore;
58-
op2 loc |> ignore;
59-
op1 loc |> ignore;
60-
op2 loc |> ignore;
61-
loop (i - (2 * 10))
62-
end
63-
in
64-
loop n_iter
54+
match op with
55+
| Get ->
56+
let rec loop i =
57+
if i > 0 then begin
58+
Sys.opaque_identity (Ref.get loc) |> ignore;
59+
Sys.opaque_identity (Ref.get loc) |> ignore;
60+
loop (i - 2)
61+
end
62+
in
63+
loop n_iter
64+
| Incr ->
65+
let rec loop i =
66+
if i > 0 then begin
67+
Ref.incr loc;
68+
Ref.incr loc;
69+
loop (i - 2)
70+
end
71+
in
72+
loop n_iter
73+
| Push_and_pop ->
74+
let push x = Ref.modify x (fun xs -> 101 :: xs)
75+
and pop x = Ref.modify x (function [] -> [] | _ :: xs -> xs) in
76+
let rec loop i =
77+
if i > 0 then begin
78+
push loc;
79+
pop loc |> ignore;
80+
loop (i - 2)
81+
end
82+
in
83+
loop n_iter
84+
| Cas_int ->
85+
let rec loop i =
86+
if i > 0 then begin
87+
Ref.compare_and_set loc 0 1 |> ignore;
88+
Ref.compare_and_set loc 1 0 |> ignore;
89+
loop (i - 2)
90+
end
91+
in
92+
loop n_iter
93+
| Xchg_int ->
94+
let rec loop i =
95+
if i > 0 then begin
96+
Ref.exchange loc 1 |> ignore;
97+
Ref.exchange loc 0 |> ignore;
98+
loop (i - 2)
99+
end
100+
in
101+
loop n_iter
102+
| Swap ->
103+
let swap x = Ref.modify x (fun (x, y) -> (y, x)) in
104+
let rec loop i =
105+
if i > 0 then begin
106+
swap loc;
107+
swap loc;
108+
loop (i - 2)
109+
end
110+
in
111+
loop n_iter
65112
in
66113

67114
Times.record ~budgetf ~n_domains:1 ~init ~work ()
68115
|> Times.to_thruput_metrics ~n:n_iter ~singular:"op" ~config:name
69116

70117
let run_suite ~budgetf =
71118
[
72-
(let get x = Ref.get x in
73-
Op ("get", 10, 42, get, get));
74-
(let incr x = Ref.incr x in
75-
Op ("incr", 1, 0, incr, incr));
76-
(let push x = Ref.modify x (fun xs -> 101 :: xs)
77-
and pop x = Ref.modify x (function [] -> [] | _ :: xs -> xs) in
78-
Op ("push & pop", 2, [], push, pop));
79-
(let cas01 x = Ref.compare_and_set x 0 1
80-
and cas10 x = Ref.compare_and_set x 1 0 in
81-
Op ("cas int", 1, 0, cas01, cas10));
82-
(let xchg1 x = Ref.exchange x 1 and xchg0 x = Ref.exchange x 0 in
83-
Op ("xchg int", 1, 0, xchg1, xchg0));
84-
(let swap x = Ref.modify x (fun (x, y) -> (y, x)) in
85-
Op ("swap", 2, (4, 2), swap, swap));
119+
run_one ~budgetf Get;
120+
run_one ~budgetf Incr;
121+
run_one ~budgetf Push_and_pop;
122+
run_one ~budgetf Cas_int;
123+
run_one ~budgetf Xchg_int;
124+
run_one ~budgetf Swap;
86125
]
87-
|> List.concat_map @@ run_one ~budgetf
126+
|> List.concat

0 commit comments

Comments
 (0)