diff --git a/backoff/Backoff/index.html b/backoff/Backoff/index.html new file mode 100644 index 00000000..1565e9bc --- /dev/null +++ b/backoff/Backoff/index.html @@ -0,0 +1,2 @@ + +Backoff (backoff.Backoff)

Module Backoff

Randomized exponential backoff mechanism.

type t

Type of backoff values.

val max_wait_log : int

Logarithm of the maximum allowed value for wait.

val create : ?lower_wait_log:int -> ?upper_wait_log:int -> unit -> t

create creates a backoff value. upper_wait_log, lower_wait_log override the logarithmic upper and lower bound on the number of spins executed by once.

val default : t

default is equivalent to create ().

val once : t -> t

once b executes one random wait and returns a new backoff with logarithm of the current maximum value incremented unless it is already at upper_wait_log of b.

Note that this uses the default Stdlib Random per-domain generator.

val reset : t -> t

reset b returns a backoff equivalent to b except with current value set to the lower_wait_log of b.

val get_wait_log : t -> int

get_wait_log b returns logarithm of the maximum value of wait for next once.

diff --git a/backoff/_doc-dir/CHANGES.md b/backoff/_doc-dir/CHANGES.md new file mode 100644 index 00000000..7e01cc5d --- /dev/null +++ b/backoff/_doc-dir/CHANGES.md @@ -0,0 +1,7 @@ +## 0.1.1 + +- Ported to 4.12 and optimized for size (@polytypic) + +## 0.1.0 + +- Initial version based on backoff from kcas (@lyrm, @polytypic) diff --git a/backoff/_doc-dir/LICENSE.md b/backoff/_doc-dir/LICENSE.md new file mode 100644 index 00000000..e107a366 --- /dev/null +++ b/backoff/_doc-dir/LICENSE.md @@ -0,0 +1,16 @@ +Copyright (c) 2015, Théo Laurent +Copyright (c) 2016, KC Sivaramakrishnan +Copyright (c) 2021, Sudha Parimala +Copyright (c) 2023, Vesa Karvonen + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/backoff/_doc-dir/README.md b/backoff/_doc-dir/README.md new file mode 100644 index 00000000..36d05f61 --- /dev/null +++ b/backoff/_doc-dir/README.md @@ -0,0 +1,94 @@ +[API reference](https://ocaml-multicore.github.io/backoff/doc/backoff/Backoff/index.html) + +# backoff - exponential backoff mechanism + +**backoff** provides an +[exponential backoff mechanism](https://en.wikipedia.org/wiki/Exponential_backoff) +[1]. It reduces contention by making a domain back off after failing an +operation contested by another domain, like acquiring a lock or performing a +`CAS` operation. + +## About contention + +Contention is what happens when multiple CPU cores try to access the same +location(s) in parallel. Let's take the example of multiple CPU cores trying to +perform a `CAS` on the same location at the same time. Only one is going to +success at each round of retries. By writing on a shared location, it +invalidates all other CPUs' caches. So at each round each CPU will have to read +the memory location again, leading to quadratic O(n²) bus traffic. + +## Exponential backoff + +Failing to access a shared resource means there is contention: some other CPU +cores are trying to access it at the same time. To avoid quadratic bus traffic, +the idea exploited by exponential backoff is to make each CPU core wait (spin) a +random bit before retrying. This way, they will try to access the resource at a +different time: that not only strongly decreases bus traffic but that also gets +them a better chance to get the resource, at they probably will compete for it +against less other CPU cores. Failing again probably means contention is high, +and they need to wait longer. In fact, each consecutive fail of a single CPU +core will make it wait twice longer (_exponential_ backoff !). + +Obviously, they cannot wait forever: there is an upper limit on the number of +times the initial waiting time can be doubled (see [Tuning](#tuning)), but +intuitively, a good waiting time should be at least around the time the +contested operation takes (in our example, the operation is a CAS) and at most a +few times that amount. + +## Tuning + +For better performance, backoff can be tuned. `Backoff.create` function has two +optional arguments for that: `upper_wait_log` and `lower_wait_log` that defines +the logarithmic upper and lower bound on the number of spins executed by +{!once}. + +## Drawbacks + +This mechanism has some drawbacks. First, it adds some delays: for example, when +a domain releases a contended lock, another domain, that has backed off after +failing acquiring it, will still have to finish its back-off loop before +retrying. Second, this increases any unfairness: any other thread that arrives +at that time or that has failed acquiring the lock for a lesser number of times +is more likely to acquire it as it will probably have a shorter waiting time. + +## Example + +To illustrate how to use backoff, here is a small implementation of +`test and test-and-set` spin lock [2]. + +```ocaml + type t = bool Atomic.t + + let create () = Atomic.make false + + let rec acquire ?(backoff = Backoff.detault) t = + if Atomic.get t then begin + Domain.cpu_relax (); + acquire ~backoff t + end + else if not (Atomic.compare_and_set t false true) then + acquire ~backoff:(Backoff.once backoff) t + + let release t = Atomic.set t false +``` + +This implementation can also be found [here](bench/taslock.ml), as well as a +small [benchmark](bench/test_tas.ml) to compare it to the same TAS lock but +without backoff. It can be launched with: + +```sh +dune exec ./bench/test_tas.exe > bench.data +``` + +and displayed (on linux) with: + +```sh +gnuplot -p -e 'plot for [col=2:4] "bench.data" using 1:col with lines title columnheader' +``` + +## References + +[1] Adaptive backoff synchronization techniques, A. Agarwal, M. Cherian (1989) + +[2] Dynamic Decentralized Cache Schemes for MIMD Parallel Processors, L.Rudolf, +Z.Segall (1984) diff --git a/backoff/index.html b/backoff/index.html new file mode 100644 index 00000000..e1ed5a09 --- /dev/null +++ b/backoff/index.html @@ -0,0 +1,2 @@ + +index (backoff.index)

Package backoff

  • Backoff Randomized exponential backoff mechanism.

Package info

changes-files
license-files
readme-files
diff --git a/index.html b/index.html index cdf52b47..cb33e7af 100644 --- a/index.html +++ b/index.html @@ -1,2 +1,2 @@ -_opam

OCaml package documentation

Browse by name, by tag, the standard library and the OCaml manual (online, latest version).

Generated for /home/runner/work/moonpool/moonpool/_opam/lib

\ No newline at end of file +_opam

OCaml package documentation

Browse by name, by tag, the standard library and the OCaml manual (online, latest version).

Generated for /home/runner/work/moonpool/moonpool/_opam/lib

\ No newline at end of file