perf: also use the main domain, along with n-1 other ones

we always keep a thread alive on the main domain as a worker for new
tasks, but other domains can still come and go to manage resources
properly in case a pool is started and used only for a short while.
This commit is contained in:
Simon Cruanes 2023-10-28 11:59:20 -04:00
parent def384b4f8
commit 7a36783e8b
2 changed files with 11 additions and 3 deletions

View file

@ -18,9 +18,7 @@ type worker_state = {
including a work queue and a thread refcount; and the domain itself,
if any, in a separate option because it might outlive its own state. *)
let domains_ : (worker_state option * Domain_.t option) Lock.t array =
(* number of domains we spawn. Note that we spawn n-1 domains
because there already is the main domain running. *)
let n = max 1 (Domain_.recommended_number () - 1) in
let n = max 1 (Domain_.recommended_number ()) in
Array.init n (fun _ -> Lock.create (None, None))
(** main work loop for a domain worker.
@ -84,6 +82,14 @@ let work_ idx (st : worker_state) : unit =
done;
()
(* special case for main domain: we start a worker immediately *)
let () =
assert (Domain_.is_main_domain ());
let w = { th_count = Atomic_.make 1; q = Bb_queue.create () } in
(* thread that stays alive *)
ignore (Thread.create (fun () -> work_ 0 w) () : Thread.t);
domains_.(0) <- Lock.create (Some w, None)
let[@inline] n_domains () : int = Array.length domains_
let run_on (i : int) (f : unit -> unit) : unit =

View file

@ -9,6 +9,7 @@ let get_id (self : t) : int = (Domain.get_id self :> int)
let spawn : _ -> t = Domain.spawn
let relax = Domain.cpu_relax
let join = Domain.join
let is_main_domain = Domain.is_main_domain
[@@@ocaml.alert "+unstable"]
[@@@else_]
@ -21,5 +22,6 @@ let get_id (self : t) : int = Thread.id self
let spawn f : t = Thread.create f ()
let relax () = Thread.yield ()
let join = Thread.join
let is_main_domain () = true
[@@@endif]