mirror of
https://github.com/c-cube/moonpool.git
synced 2025-12-05 19:00:33 -05:00
* feat: depend on picos, use picos.exn_bt * refactor: remove dla * non optional dependency on thread-local-storage it's a dep of picos anyway * wip: use picos computations * disable t_fib1 test, way too flaky * feat `fut`: wrap picos computations * detail in fut * gitignore * refactor core: use picos for schedulers; add Worker_loop_ we factor most of the thread workers' logic in `Worker_loop_`, which is now shared between Ws_pool and Fifo_pool * github actions * feat fut: add `on_result_ignore` * details * wip: port to picos * test: wip porting tests * fix fut: trigger failing to attach doesn't signal it * fix pool: only return No_more_tasks when local and global q empty * format * chore: fix CI by installing picos first * more CI * test: re-enable t_fib1 but with a single core fifo pool it should be deterministic now! * fixes after reviews * bump minimal OCaml version to 4.13 * use `exn_bt`, not `picos.exn_bt` * feat: optional dep on hmap, for inheritable FLS data * format * chore: depend on picos explicitly * feat: move hmap-fls to Fiber.Fls * change API for local FLS hmap * refactor: move optional hmap FLS stuff into core/task_local_storage * add Task_local_storage.remove_in_local_hmap * chore: try to fix CI * format * chore: CI * fix * feat: add `Fls.with_in_local_hmap` * chore: depend on hmap for tests * fix test for FLS use the inheritable keys * chore: CI * require OCaml 4.14 :/ * feat: add `moonpool.sync` with await-friendly abstractions based on picos_sync * fix: catch TLS.Not_set * fix: `LS.get` shouldn't raise * fix * update to merged picos PR * chore: CI * fix dep * feat: add `Event.of_fut` * chore: CI * remove dep on now defunct `exn_bt` * feat: add moonpool-io * chore: CI * version constraint on moonpool-io * add Event.Infix * move to picos_io
177 lines
4.5 KiB
OCaml
177 lines
4.5 KiB
OCaml
open! Moonpool
|
|
module A = Atomic
|
|
module F = Moonpool_fib.Fiber
|
|
module FLS = Moonpool_fib.Fls
|
|
|
|
(* ### dummy little tracing system with local storage *)
|
|
|
|
type span_id = int
|
|
|
|
let k_parent : span_id Hmap.key = Hmap.Key.create ()
|
|
let ( let@ ) = ( @@ )
|
|
let spf = Printf.sprintf
|
|
|
|
module Span = struct
|
|
let new_id_ : unit -> span_id =
|
|
let n = A.make 0 in
|
|
fun () -> A.fetch_and_add n 1
|
|
|
|
type t = {
|
|
id: span_id;
|
|
parent: span_id option;
|
|
msg: string;
|
|
}
|
|
end
|
|
|
|
module Tracer = struct
|
|
type t = { spans: Span.t list A.t }
|
|
|
|
let create () : t = { spans = A.make [] }
|
|
let get self = A.get self.spans
|
|
|
|
let add (self : t) span =
|
|
while
|
|
let old = A.get self.spans in
|
|
not (A.compare_and_set self.spans old (span :: old))
|
|
do
|
|
()
|
|
done
|
|
|
|
let with_span self name f =
|
|
let id = Span.new_id_ () in
|
|
let parent = FLS.get_in_local_hmap_opt k_parent in
|
|
let span = { Span.id; parent; msg = name } in
|
|
add self span;
|
|
FLS.with_in_local_hmap k_parent id f
|
|
end
|
|
|
|
module Render = struct
|
|
type span_tree = {
|
|
msg: string; (** message of the span at the root *)
|
|
children: span_tree list;
|
|
}
|
|
|
|
type t = { roots: span_tree list }
|
|
|
|
let build (tracer : Tracer.t) : t =
|
|
let tops : (span_id, Span.t) Hashtbl.t = Hashtbl.create 16 in
|
|
let children : (span_id, Span.t list) Hashtbl.t = Hashtbl.create 16 in
|
|
|
|
(* everyone is a root at first *)
|
|
let all_spans = Tracer.get tracer in
|
|
List.iter (fun (sp : Span.t) -> Hashtbl.add tops sp.id sp) all_spans;
|
|
|
|
(* now consider the parenting relationships *)
|
|
let add_span_to_parent (span : Span.t) =
|
|
match span.parent with
|
|
| None -> ()
|
|
| Some p ->
|
|
Hashtbl.remove tops span.id;
|
|
let l = try Hashtbl.find children p with Not_found -> [] in
|
|
Hashtbl.replace children p (span :: l)
|
|
in
|
|
List.iter add_span_to_parent all_spans;
|
|
|
|
(* build the tree *)
|
|
let rec build_tree (sp : Span.t) : span_tree =
|
|
let children = try Hashtbl.find children sp.id with Not_found -> [] in
|
|
let children = List.map build_tree children |> List.sort Stdlib.compare in
|
|
{ msg = sp.msg; children }
|
|
in
|
|
|
|
let roots =
|
|
Hashtbl.fold (fun _ sp l -> build_tree sp :: l) tops []
|
|
|> List.sort Stdlib.compare
|
|
in
|
|
|
|
{ roots }
|
|
|
|
let pp (oc : out_channel) (self : t) : unit =
|
|
let rec pp_tree indent out (t : span_tree) =
|
|
let prefix = String.make indent ' ' in
|
|
Printf.fprintf out "%s%S\n" prefix t.msg;
|
|
List.iter (pp_tree (indent + 2) out) t.children
|
|
in
|
|
List.iter (pp_tree 2 oc) self.roots
|
|
end
|
|
|
|
let run ~pool ~pool_name () =
|
|
let tracer = Tracer.create () in
|
|
|
|
let sub_sub_child ~idx ~idx_child ~idx_sub ~idx_sub_sub () =
|
|
let@ () =
|
|
Tracer.with_span tracer
|
|
(spf "child_%d.%d.%d.%d" idx idx_child idx_sub idx_sub_sub)
|
|
in
|
|
|
|
for j = 1 to 5 do
|
|
let@ () = Tracer.with_span tracer (spf "iter.loop %d" j) in
|
|
F.yield ()
|
|
done
|
|
in
|
|
|
|
let sub_child ~idx ~idx_child ~idx_sub () =
|
|
let@ () =
|
|
Tracer.with_span tracer (spf "child_%d.%d.%d" idx idx_child idx_sub)
|
|
in
|
|
|
|
for i = 1 to 10 do
|
|
let@ () = Tracer.with_span tracer (spf "iter.loop %02d" i) in
|
|
F.yield ()
|
|
done;
|
|
|
|
let subs =
|
|
List.init 2 (fun idx_sub_sub ->
|
|
F.spawn ~protect:true (fun () ->
|
|
sub_sub_child ~idx ~idx_child ~idx_sub ~idx_sub_sub ()))
|
|
in
|
|
List.iter F.await subs
|
|
in
|
|
|
|
let top_child ~idx ~idx_child () =
|
|
let@ () = Tracer.with_span tracer (spf "child.%d.%d" idx idx_child) in
|
|
|
|
let subs =
|
|
List.init 2 (fun k ->
|
|
F.spawn ~protect:true @@ fun () ->
|
|
sub_child ~idx ~idx_child ~idx_sub:k ())
|
|
in
|
|
|
|
let@ () =
|
|
Tracer.with_span tracer
|
|
(spf "child.%d.%d.99.await_children" idx idx_child)
|
|
in
|
|
List.iter F.await subs
|
|
in
|
|
|
|
let top idx =
|
|
let@ () = Tracer.with_span tracer (spf "top_%d" idx) in
|
|
|
|
let subs =
|
|
List.init 5 (fun j ->
|
|
F.spawn ~protect:true @@ fun () -> top_child ~idx ~idx_child:j ())
|
|
in
|
|
|
|
List.iter F.await subs
|
|
in
|
|
|
|
Printf.printf "run test on pool = %s\n" pool_name;
|
|
let fibs =
|
|
List.init 8 (fun idx -> F.spawn_top ~on:pool (fun () -> top idx))
|
|
in
|
|
List.iter F.wait_block_exn fibs;
|
|
|
|
Printf.printf "tracing complete\n";
|
|
Printf.printf "spans:\n";
|
|
let tree = Render.build tracer in
|
|
Render.pp stdout tree;
|
|
Printf.printf "done\n%!";
|
|
()
|
|
|
|
let () =
|
|
(let@ pool = Ws_pool.with_ () in
|
|
run ~pool ~pool_name:"ws_pool" ());
|
|
|
|
(let@ pool = Fifo_pool.with_ () in
|
|
run ~pool ~pool_name:"ws_pool" ());
|
|
()
|