Skip to content

Commit ae9ca48

Browse files
authored
Merge branch 'main' into add-native-pack-linker-variable
2 parents 79d0e07 + 4db21fe commit ae9ca48

File tree

19 files changed

+724
-34
lines changed

19 files changed

+724
-34
lines changed

bench/bench.ml

+8-4
Original file line numberDiff line numberDiff line change
@@ -143,11 +143,15 @@ let () =
143143
stat.st_size
144144
in
145145
let results =
146-
[ { Output.name = "clean_build"
147-
; metrics = [ ("time", `Float clean, "secs") ]
146+
[ { Output.name = "Build times"
147+
; metrics =
148+
[ ("Clean build time", `Float clean, "secs")
149+
; ("Null build time", `List zero, "secs")
150+
]
151+
}
152+
; { Output.name = "Misc"
153+
; metrics = [ ("Size of dune.exe", `Int size, "bytes") ]
148154
}
149-
; { Output.name = "zero_build"; metrics = [ ("time", `List zero, "secs") ] }
150-
; { Output.name = "dune_size"; metrics = [ ("size", `Int size, "bytes") ] }
151155
]
152156
in
153157
let version = 2 in

bench/micro/dune

+6
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,9 @@
2525
(allow_overlapping_dependencies)
2626
(modules fiber_bench_main)
2727
(libraries fiber_bench core_bench.inline_benchmarks))
28+
29+
(executable
30+
(name memo_bench_main)
31+
(allow_overlapping_dependencies)
32+
(modules memo_bench_main)
33+
(libraries memo_bench core_bench.inline_benchmarks))

bench/micro/memo_bench/benchmarks.ml

+194
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
open Stdune
2+
3+
let invalidation_acc = ref Memo.Invalidation.empty
4+
5+
module Build = struct
6+
include Memo.Build
7+
8+
let sample_count =
9+
(* Count number of samples of all lifted computations, to allow simple
10+
detection of looping tests executed by [run] *)
11+
ref 0
12+
13+
let exec build =
14+
(* not expected to be used in re-entrant way *)
15+
sample_count := 0;
16+
Memo.reset !invalidation_acc;
17+
invalidation_acc := Memo.Invalidation.empty;
18+
let fiber = Memo.Build.run build in
19+
Fiber.run fiber ~iter:(fun _ -> failwith "deadlock?")
20+
21+
let memoize t =
22+
let l = Memo.lazy_ ~cutoff:(fun _ _ -> false) (fun () -> t) in
23+
Memo.Build.of_thunk (fun () -> Memo.Lazy.force l)
24+
25+
let map2 x y ~f =
26+
map
27+
~f:(fun (x, y) -> f x y)
28+
(Memo.Build.fork_and_join (fun () -> x) (fun () -> y))
29+
30+
let all l = Memo.Build.all_concurrently l
31+
end
32+
33+
let run tenacious = Build.exec tenacious
34+
35+
module Var = struct
36+
type 'a t =
37+
{ value : 'a ref
38+
; cell : (unit, 'a) Memo.Cell.t
39+
}
40+
41+
let create value =
42+
let value = ref value in
43+
{ value
44+
; cell =
45+
Memo.lazy_cell
46+
~cutoff:(fun _ _ -> false)
47+
(fun () -> Memo.Build.return !value)
48+
}
49+
50+
let set t v =
51+
t.value := v;
52+
invalidation_acc :=
53+
Memo.Invalidation.combine !invalidation_acc
54+
(Memo.Cell.invalidate ~reason:Memo.Invalidation.Reason.Test t.cell)
55+
56+
let read t = Memo.Build.of_thunk (fun () -> Memo.Cell.read t.cell)
57+
58+
let peek t = !(t.value)
59+
end
60+
61+
let incr v = Var.set v (Var.peek v)
62+
63+
module Case = struct
64+
(* The first [unit] it to delay the creation of functions until benchmarking
65+
is ready to run. *)
66+
type 'a t =
67+
{ create_and_compute : unit -> unit -> 'a
68+
; incr_and_recompute : unit -> unit -> 'a
69+
; restore_from_cache : unit -> unit -> 'a
70+
}
71+
72+
let create (f : unit -> _ Var.t * 'a Build.t) : 'a t =
73+
let create_and_compute () () = run (f () |> snd) in
74+
let incr_and_recompute () =
75+
let var, build = f () in
76+
let (_ : 'a) = run build in
77+
fun () ->
78+
incr var;
79+
run build
80+
in
81+
let restore_from_cache () =
82+
let build = f () |> snd in
83+
let (_ : 'a) = run build in
84+
fun () -> run build
85+
in
86+
{ create_and_compute; incr_and_recompute; restore_from_cache }
87+
end
88+
89+
let one_bind =
90+
Case.create (fun () ->
91+
let v = Var.create 0 in
92+
( v
93+
, List.fold_left ~init:(Build.return 0)
94+
(List.init 1 ~f:(fun _i -> ()))
95+
~f:(fun acc () ->
96+
Build.bind acc ~f:(fun acc ->
97+
Build.map (Var.read v) ~f:(fun v -> acc + v))) ))
98+
99+
let%bench_fun "1-bind (create and compute)" = one_bind.create_and_compute ()
100+
101+
let%bench_fun "1-bind (incr and recompute)" = one_bind.incr_and_recompute ()
102+
103+
let%bench_fun "1-bind (restore from cache)" = one_bind.restore_from_cache ()
104+
105+
let twenty_reads =
106+
Case.create (fun () ->
107+
let v = Var.create 0 in
108+
( v
109+
, List.fold_left ~init:(Build.return 0)
110+
(List.init 20 ~f:(fun _i -> ()))
111+
~f:(fun acc () ->
112+
Build.bind acc ~f:(fun acc ->
113+
Build.map (Var.read v) ~f:(fun v -> acc + v))) ))
114+
115+
let%bench_fun "20-reads (create and compute)" =
116+
twenty_reads.create_and_compute ()
117+
118+
let%bench_fun "20-reads (incr and recompute)" =
119+
twenty_reads.incr_and_recompute ()
120+
121+
let%bench_fun "20-reads (restore from cache)" =
122+
twenty_reads.restore_from_cache ()
123+
124+
let clique =
125+
Case.create (fun () ->
126+
let v = Var.create 0 in
127+
let read_v = Build.memoize (Var.read v) in
128+
( v
129+
, List.fold_left ~init:read_v
130+
(List.init 30 ~f:(fun _i -> ()))
131+
~f:(fun acc () ->
132+
let node = Build.memoize acc in
133+
Build.map2 node acc ~f:( + )) ))
134+
135+
let%bench_fun "clique (create and compute)" = clique.create_and_compute ()
136+
137+
let%bench_fun "clique (incr and recompute)" = clique.incr_and_recompute ()
138+
139+
let%bench_fun "clique (restore from cache)" = clique.restore_from_cache ()
140+
141+
let bipartite =
142+
Case.create (fun () ->
143+
let first_var = Var.create 0 in
144+
let inputs =
145+
List.init 30 ~f:(fun i ->
146+
let v =
147+
if i = 0 then
148+
first_var
149+
else
150+
Var.create 0
151+
in
152+
Build.memoize (Var.read v))
153+
in
154+
let matrix i j =
155+
if i = j then
156+
1
157+
else
158+
0
159+
in
160+
let outputs =
161+
List.init 30 ~f:(fun i ->
162+
Build.memoize
163+
(Build.all
164+
(List.mapi inputs ~f:(fun j x ->
165+
Build.map x ~f:(fun x -> matrix i j * x)))
166+
|> Build.map ~f:(List.fold_left ~init:0 ~f:( + ))))
167+
in
168+
(first_var, Build.memoize (Build.all outputs)))
169+
170+
let%bench_fun "bipartite (create and compute)" = bipartite.create_and_compute ()
171+
172+
let%bench_fun "bipartite (incr and recompute)" = bipartite.incr_and_recompute ()
173+
174+
let%bench_fun "bipartite (restore from cache)" = bipartite.restore_from_cache ()
175+
176+
let memo_diamonds =
177+
Case.create (fun () ->
178+
let v = Var.create 0 in
179+
( v
180+
, List.fold_left ~init:(Var.read v)
181+
(List.init 20 ~f:(fun _i -> ()))
182+
~f:(fun acc () ->
183+
Build.memoize
184+
(Build.bind acc ~f:(fun x -> Build.map acc ~f:(fun y -> x + y))))
185+
))
186+
187+
let%bench_fun "memo diamonds (create and compute)" =
188+
memo_diamonds.create_and_compute ()
189+
190+
let%bench_fun "memo diamonds (incr and recompute)" =
191+
memo_diamonds.incr_and_recompute ()
192+
193+
let%bench_fun "memo diamonds (restore from cache)" =
194+
memo_diamonds.restore_from_cache ()

bench/micro/memo_bench/benchmarks.mli

Whitespace-only changes.

bench/micro/memo_bench/dune

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
(library
2+
(name memo_bench)
3+
(library_flags -linkall)
4+
(preprocess
5+
(pps ppx_bench))
6+
(libraries fiber stdune memo core_bench.inline_benchmarks))

bench/micro/memo_bench/memo_intf.ml

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
module type Monad_intf = sig
2+
type 'a t
3+
4+
val return : 'a -> 'a t
5+
val bind : 'a t -> f:('a -> 'b t) -> 'b t
6+
val map : 'a t -> f:('a -> 'b) -> 'b t
7+
8+
module Let_syntax : sig
9+
val return : 'a -> 'a t
10+
val ( let* ) : 'a t -> ('a -> 'b t) -> 'b t
11+
val ( let+ ) : 'a t -> ('a -> 'b) -> 'b t
12+
end
13+
end
14+
15+
module type Test_env = sig
16+
module Glass : sig
17+
type t
18+
19+
val create : unit -> t
20+
val break : t -> unit
21+
end
22+
23+
module Io : sig
24+
include Monad_intf
25+
26+
module Ivar : sig
27+
type 'a io := 'a t
28+
type 'a t
29+
30+
val create : unit -> 'a t
31+
val read : 'a t -> 'a io
32+
val fill : 'a t -> 'a -> unit io
33+
end
34+
35+
val of_thunk : (unit -> 'a t) -> 'a t
36+
end
37+
38+
module Build : sig
39+
include Monad_intf
40+
41+
val map2 : 'a t -> 'b t -> f:('a -> 'b -> 'c) -> 'c t
42+
val all : 'a t list -> 'a list t
43+
val of_glass : Glass.t -> 'a -> 'a t
44+
val of_thunk : (unit -> 'a t) -> 'a t
45+
val of_io : (unit -> 'a Io.t) -> 'a t
46+
val memoize : 'a t -> 'a t
47+
end
48+
49+
module Var : sig
50+
type 'a t
51+
52+
val create : 'a -> 'a t
53+
val set : 'a t -> 'a -> unit
54+
val read : 'a t -> 'a Build.t
55+
56+
(** peek once without registering interest in future updates *)
57+
val peek : 'a t -> 'a
58+
end
59+
60+
val run : 'a Build.t -> 'a
61+
val make_counter : unit -> int Build.t * (unit -> unit)
62+
end

0 commit comments

Comments
 (0)