-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Co-authored-by: Jan Midtgaard <mail@janmidtgaard.dk>
- Loading branch information
Showing
27 changed files
with
934 additions
and
69 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
open Multicore_bench | ||
|
||
module Htbl = struct | ||
open Picos_std_sync | ||
module Htbl = Picos_aux_htbl | ||
|
||
type ('k, 'v) t = { htbl : ('k, 'v) Htbl.t; rwlock : Rwlock.t } | ||
|
||
let create ?hashed_type () = | ||
{ | ||
htbl = Htbl.create ?hashed_type (); | ||
rwlock = Rwlock.create ~padded:true (); | ||
} | ||
|
||
let remove_all t = Htbl.remove_all t.htbl | ||
|
||
let find_opt t key = | ||
Rwlock.lock_ro t.rwlock; | ||
let result = | ||
match Htbl.find_exn t.htbl key with | ||
| value -> Some value | ||
| exception Not_found -> None | ||
in | ||
Rwlock.unlock t.rwlock; | ||
result | ||
|
||
let try_add t key value = | ||
Rwlock.lock t.rwlock; | ||
let result = Htbl.try_add t.htbl key value in | ||
Rwlock.unlock t.rwlock; | ||
result | ||
|
||
let try_remove t key = | ||
Rwlock.lock t.rwlock; | ||
let result = Htbl.try_remove t.htbl key in | ||
Rwlock.unlock t.rwlock; | ||
result | ||
end | ||
|
||
module Key = struct | ||
type t = int | ||
|
||
let equal = Int.equal | ||
let hash = Fun.id | ||
end | ||
|
||
let run_one ~budgetf ~n_domains ?(n_ops = 100 * Util.iter_factor) | ||
?(n_keys = 1000) ~percent_mem ?(percent_add = (100 - percent_mem + 1) / 2) | ||
?(prepopulate = true) () = | ||
let limit_mem = percent_mem in | ||
let limit_add = percent_mem + percent_add in | ||
|
||
assert (0 <= limit_mem && limit_mem <= 100); | ||
assert (limit_mem <= limit_add && limit_add <= 100); | ||
|
||
let t = Htbl.create ~hashed_type:(module Key) () in | ||
|
||
let n_ops = (100 + percent_mem) * n_ops / 100 in | ||
let n_ops = n_ops * n_domains in | ||
|
||
let n_ops_todo = Countdown.create ~n_domains () in | ||
|
||
let before () = | ||
let _ : _ Seq.t = Htbl.remove_all t in | ||
Countdown.non_atomic_set n_ops_todo n_ops | ||
in | ||
let init i = | ||
Scheduler.run @@ fun () -> | ||
let state = Random.State.make_self_init () in | ||
if prepopulate then begin | ||
let n = ((i + 1) * n_keys / n_domains) - (i * n_keys / n_domains) in | ||
for _ = 1 to n do | ||
let value = Random.State.bits state in | ||
let key = value mod n_keys in | ||
Htbl.try_add t key value |> ignore | ||
done | ||
end; | ||
state | ||
in | ||
let wrap _ _ = Scheduler.run in | ||
let work domain_index state = | ||
let rec work () = | ||
let n = Countdown.alloc n_ops_todo ~domain_index ~batch:1000 in | ||
if n <> 0 then begin | ||
for _ = 1 to n do | ||
let value = Random.State.bits state in | ||
let op = (value asr 20) mod 100 in | ||
let key = value mod n_keys in | ||
if op < percent_mem then Htbl.find_opt t key |> ignore | ||
else if op < limit_add then Htbl.try_add t key value |> ignore | ||
else Htbl.try_remove t key |> ignore | ||
done; | ||
work () | ||
end | ||
in | ||
work () | ||
in | ||
|
||
let config = | ||
Printf.sprintf "%d worker%s, %d%% reads" n_domains | ||
(if n_domains = 1 then "" else "s") | ||
percent_mem | ||
in | ||
Times.record ~budgetf ~n_domains ~n_warmups:1 ~n_runs_min:1 ~before ~init | ||
~wrap ~work () | ||
|> Times.to_thruput_metrics ~n:n_ops ~singular:"operation" ~config | ||
|
||
let run_suite ~budgetf = | ||
Util.cross [ 1; 2; 4; 8 ] [ 10; 50; 90; 95; 100 ] | ||
|> List.concat_map @@ fun (n_domains, percent_mem) -> | ||
if Picos_domain.recommended_domain_count () < n_domains then [] | ||
else run_one ~budgetf ~n_domains ~percent_mem () |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
open Picos | ||
open Picos_std_awaitable | ||
|
||
type t = unit Awaitable.t | ||
|
||
let create ?padded () = Awaitable.make ?padded () | ||
|
||
let[@inline] wait t mutex ~lock ~unlock = | ||
let trigger = Trigger.create () in | ||
let awaiter = Awaitable.Awaiter.add t trigger in | ||
unlock mutex; | ||
let lock_forbidden mutex = | ||
let fiber = Fiber.current () in | ||
let forbid = Fiber.exchange fiber ~forbid:true in | ||
lock mutex; | ||
Fiber.set fiber ~forbid | ||
in | ||
match Trigger.await trigger with | ||
| None -> lock_forbidden mutex | ||
| Some exn_bt -> | ||
Awaitable.Awaiter.remove awaiter; | ||
lock_forbidden mutex; | ||
Printexc.raise_with_backtrace (fst exn_bt) (snd exn_bt) | ||
|
||
let signal = Awaitable.signal | ||
let broadcast = Awaitable.broadcast |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
module type Condition = sig | ||
type mutex | ||
(** Represents a mutual exclusion lock. *) | ||
|
||
type t | ||
(** Represents a condition variable *) | ||
|
||
val create : ?padded:bool -> unit -> t | ||
(** [create ()] return a new condition variable. *) | ||
|
||
val wait : t -> mutex -> unit | ||
(** [wait condition mutex] unlocks the [mutex], waits for the [condition], and | ||
locks the [mutex] before returning or raising due to the operation being | ||
canceled. | ||
ℹ️ If the fiber has been canceled and propagation of cancelation is | ||
allowed, this may raise the cancelation exception. *) | ||
|
||
val signal : t -> unit | ||
(** [signal condition] wakes up one fiber waiting on the [condition] variable | ||
unless there are no such fibers. *) | ||
|
||
val broadcast : t -> unit | ||
(** [broadcast condition] wakes up all the fibers waiting on the [condition] | ||
variable. *) | ||
end |
Oops, something went wrong.