-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
118 changed files
with
3,059 additions
and
43 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
<!DOCTYPE html> | ||
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Backoff (backoff.Backoff)</title><meta charset="utf-8"/><link rel="stylesheet" href="../../_odoc-theme/odoc.css"/><meta name="generator" content="odoc 2.4.2"/><meta name="viewport" content="width=device-width,initial-scale=1.0"/><script src="../../highlight.pack.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body class="odoc"><nav class="odoc-nav"><a href="../index.html">Up</a> – <a href="../index.html">backoff</a> » Backoff</nav><header class="odoc-preamble"><h1>Module <code><span>Backoff</span></code></h1><p>Randomized exponential backoff mechanism.</p></header><div class="odoc-content"><div class="odoc-spec"><div class="spec type anchored" id="type-t"><a href="#type-t" class="anchor"></a><code><span><span class="keyword">type</span> t</span></code></div><div class="spec-doc"><p>Type of backoff values.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-max_wait_log"><a href="#val-max_wait_log" class="anchor"></a><code><span><span class="keyword">val</span> max_wait_log : int</span></code></div><div class="spec-doc"><p>Logarithm of the maximum allowed value for wait.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-create"><a href="#val-create" class="anchor"></a><code><span><span class="keyword">val</span> create : <span><span class="optlabel">?lower_wait_log</span>:int <span class="arrow">-></span></span> <span><span class="optlabel">?upper_wait_log</span>:int <span class="arrow">-></span></span> <span>unit <span class="arrow">-></span></span> <a href="#type-t">t</a></span></code></div><div class="spec-doc"><p><code>create</code> creates a backoff value. <code>upper_wait_log</code>, <code>lower_wait_log</code> override the logarithmic upper and lower bound on the number of spins executed by <a href="#val-once"><code>once</code></a>.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-default"><a href="#val-default" class="anchor"></a><code><span><span class="keyword">val</span> default : <a href="#type-t">t</a></span></code></div><div class="spec-doc"><p><code>default</code> is equivalent to <code>create ()</code>.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-once"><a href="#val-once" class="anchor"></a><code><span><span class="keyword">val</span> once : <span><a href="#type-t">t</a> <span class="arrow">-></span></span> <a href="#type-t">t</a></span></code></div><div class="spec-doc"><p><code>once b</code> executes one random wait and returns a new backoff with logarithm of the current maximum value incremented unless it is already at <code>upper_wait_log</code> of <code>b</code>.</p><p>Note that this uses the default Stdlib <code>Random</code> per-domain generator.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-reset"><a href="#val-reset" class="anchor"></a><code><span><span class="keyword">val</span> reset : <span><a href="#type-t">t</a> <span class="arrow">-></span></span> <a href="#type-t">t</a></span></code></div><div class="spec-doc"><p><code>reset b</code> returns a backoff equivalent to <code>b</code> except with current value set to the <code>lower_wait_log</code> of <code>b</code>.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-get_wait_log"><a href="#val-get_wait_log" class="anchor"></a><code><span><span class="keyword">val</span> get_wait_log : <span><a href="#type-t">t</a> <span class="arrow">-></span></span> int</span></code></div><div class="spec-doc"><p><code>get_wait_log b</code> returns logarithm of the maximum value of wait for next <a href="#val-once"><code>once</code></a>.</p></div></div></div></body></html> |
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,7 @@ | ||
# Release notes | ||
|
||
All notable changes to this project will be documented in this file. | ||
|
||
## 0.1.0 | ||
|
||
- Initial version based on backoff from kcas (@lyrm, @polytypic) |
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,16 @@ | ||
Copyright (c) 2015, Théo Laurent <theo.laurent@ens.fr> | ||
Copyright (c) 2016, KC Sivaramakrishnan <kc@kcsrk.info> | ||
Copyright (c) 2021, Sudha Parimala <sudharg247@gmail.com> | ||
Copyright (c) 2023, Vesa Karvonen <vesa.a.j.k@gmail.com> | ||
|
||
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. |
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,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) |
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,2 @@ | ||
<!DOCTYPE html> | ||
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>index (backoff.index)</title><meta charset="utf-8"/><link rel="stylesheet" href="../_odoc-theme/odoc.css"/><meta name="generator" content="odoc 2.4.2"/><meta name="viewport" content="width=device-width,initial-scale=1.0"/><script src="../highlight.pack.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body class="odoc"><nav class="odoc-nav"><a href="../index.html">Up</a> – backoff</nav><header class="odoc-preamble"><h1 id="package-backoff"><a href="#package-backoff" class="anchor"></a>Package backoff <nav><a type="text/plain; charset=UTF-8" href="_doc-dir/CHANGES.md">changes</a> <a href="#package_info">more…</a></nav></h1><ul class="modules"><li><a href="Backoff/index.html"><code>Backoff</code></a> <span class="synopsis">Randomized exponential backoff mechanism.</span></li></ul></header><nav class="odoc-toc"><ul><li><a href="#package_info">Package info</a></li></ul></nav><div class="odoc-content"><h2 id="package_info"><a href="#package_info" class="anchor"></a>Package info</h2><table class="package info"><tr id="info-changes-files"><td><a href="#info-changes-files" aria-hidden="true" class="anchor"></a>changes-files</td><td><ul><li><a type="text/plain; charset=UTF-8" href="_doc-dir/CHANGES.md">CHANGES.md</a></li></ul></td></tr><tr id="info-license-files"><td><a href="#info-license-files" aria-hidden="true" class="anchor"></a>license-files</td><td><ul><li><a type="text/plain; charset=UTF-8" href="_doc-dir/LICENSE.md">LICENSE.md</a></li></ul></td></tr><tr id="info-readme-files"><td><a href="#info-readme-files" aria-hidden="true" class="anchor"></a>readme-files</td><td><ul><li><a type="text/plain; charset=UTF-8" href="_doc-dir/README.md">README.md</a></li></ul></td></tr></table></div></body></html> |
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 |
---|---|---|
@@ -1,2 +1,2 @@ | ||
<!DOCTYPE html> | ||
<html><head><meta charset="utf-8"><meta name="generator" content="odig v0.0.9"><meta name="viewport" content="width=device-width, initial-scale=1.0"><link rel="stylesheet" type="text/css" media="screen, print" href="_odoc-theme/odoc.css"><title>_opam</title></head><body class="odoc"><nav class="odoc-nav">🐫</nav><header class="odoc-preamble"><h1>OCaml package documentation</h1><p>Browse <a href="#by-name">by name</a>, <a href="#by-tag">by tag</a>, the <a href="ocaml/Stdlib/index.html#modules">standard library</a> and the <a href="https://ocaml.org/manual/">OCaml manual</a> (online, latest version).</p><p><small>Generated for <code>/home/runner/work/moonpool/moonpool/_opam/lib</code></small></p></header><nav class="odoc-toc"><ul><li><a href="ocaml/Stdlib/index.html#modules">OCaml standard library</a></li><li><a href="https://ocaml.org/manual/">OCaml manual</a></li><li><a href="#by-name">Packages by name</a></li><li><a href="#by-tag">Packages by tag</a></li></ul></nav><div class="odoc-content"><h2 id="by-name"><a href="#by-name" aria-hidden="true" class="anchor"></a>Packages by name</h2><div class="by-name"><nav><a href="#name-e">e</a><a href="#name-l">l</a><a href="#name-m">m</a><a href="#name-o">o</a></nav><h3 id="name-e"><a href="#name-e" aria-hidden="true" class="anchor"></a>e</h3><ol class="packages"><li id="package-either"><a href="#package-either" aria-hidden="true" class="anchor"></a><a href="either/index.html">either</a> <span class="version"></span> <span class="synopsis"></span></li></ol><h3 id="name-l"><a href="#name-l" aria-hidden="true" class="anchor"></a>l</h3><ol class="packages"><li id="package-lwt"><a href="#package-lwt" aria-hidden="true" class="anchor"></a><a href="lwt/index.html">lwt</a> <span class="version"></span> <span class="synopsis"></span></li></ol><h3 id="name-m"><a href="#name-m" aria-hidden="true" class="anchor"></a>m</h3><ol class="packages"><li id="package-moonpool"><a href="#package-moonpool" aria-hidden="true" class="anchor"></a><a href="moonpool/index.html">moonpool</a> <span class="version"></span> <span class="synopsis"></span></li><li id="package-moonpool-lwt"><a href="#package-moonpool-lwt" aria-hidden="true" class="anchor"></a><a href="moonpool-lwt/index.html">moonpool-lwt</a> <span class="version"></span> <span class="synopsis"></span></li></ol><h3 id="name-o"><a href="#name-o" aria-hidden="true" class="anchor"></a>o</h3><ol class="packages"><li id="package-ocaml"><a href="#package-ocaml" aria-hidden="true" class="anchor"></a><a href="ocaml/index.html">ocaml</a> <span class="version"></span> <span class="synopsis"></span></li></ol></div><h2 id="by-tag"><a href="#by-tag" aria-hidden="true" class="anchor"></a>Packages by tag</h2><div class="by-tag"><nav><table></table></nav></div></div></body></html> | ||
<html><head><meta charset="utf-8"><meta name="generator" content="odig v0.0.9"><meta name="viewport" content="width=device-width, initial-scale=1.0"><link rel="stylesheet" type="text/css" media="screen, print" href="_odoc-theme/odoc.css"><title>_opam</title></head><body class="odoc"><nav class="odoc-nav">🐫</nav><header class="odoc-preamble"><h1>OCaml package documentation</h1><p>Browse <a href="#by-name">by name</a>, <a href="#by-tag">by tag</a>, the <a href="ocaml/Stdlib/index.html#modules">standard library</a> and the <a href="https://ocaml.org/manual/">OCaml manual</a> (online, latest version).</p><p><small>Generated for <code>/home/runner/work/moonpool/moonpool/_opam/lib</code></small></p></header><nav class="odoc-toc"><ul><li><a href="ocaml/Stdlib/index.html#modules">OCaml standard library</a></li><li><a href="https://ocaml.org/manual/">OCaml manual</a></li><li><a href="#by-name">Packages by name</a></li><li><a href="#by-tag">Packages by tag</a></li></ul></nav><div class="odoc-content"><h2 id="by-name"><a href="#by-name" aria-hidden="true" class="anchor"></a>Packages by name</h2><div class="by-name"><nav><a href="#name-b">b</a><a href="#name-e">e</a><a href="#name-l">l</a><a href="#name-m">m</a><a href="#name-o">o</a><a href="#name-p">p</a><a href="#name-t">t</a></nav><h3 id="name-b"><a href="#name-b" aria-hidden="true" class="anchor"></a>b</h3><ol class="packages"><li id="package-backoff"><a href="#package-backoff" aria-hidden="true" class="anchor"></a><a href="backoff/index.html">backoff</a> <span class="version"></span> <span class="synopsis"></span></li></ol><h3 id="name-e"><a href="#name-e" aria-hidden="true" class="anchor"></a>e</h3><ol class="packages"><li id="package-either"><a href="#package-either" aria-hidden="true" class="anchor"></a><a href="either/index.html">either</a> <span class="version"></span> <span class="synopsis"></span></li></ol><h3 id="name-l"><a href="#name-l" aria-hidden="true" class="anchor"></a>l</h3><ol class="packages"><li id="package-lwt"><a href="#package-lwt" aria-hidden="true" class="anchor"></a><a href="lwt/index.html">lwt</a> <span class="version"></span> <span class="synopsis"></span></li></ol><h3 id="name-m"><a href="#name-m" aria-hidden="true" class="anchor"></a>m</h3><ol class="packages"><li id="package-moonpool"><a href="#package-moonpool" aria-hidden="true" class="anchor"></a><a href="moonpool/index.html">moonpool</a> <span class="version"></span> <span class="synopsis"></span></li><li id="package-moonpool-lwt"><a href="#package-moonpool-lwt" aria-hidden="true" class="anchor"></a><a href="moonpool-lwt/index.html">moonpool-lwt</a> <span class="version"></span> <span class="synopsis"></span></li><li id="package-multicore-magic"><a href="#package-multicore-magic" aria-hidden="true" class="anchor"></a><a href="multicore-magic/index.html">multicore-magic</a> <span class="version"></span> <span class="synopsis"></span></li></ol><h3 id="name-o"><a href="#name-o" aria-hidden="true" class="anchor"></a>o</h3><ol class="packages"><li id="package-ocaml"><a href="#package-ocaml" aria-hidden="true" class="anchor"></a><a href="ocaml/index.html">ocaml</a> <span class="version"></span> <span class="synopsis"></span></li></ol><h3 id="name-p"><a href="#name-p" aria-hidden="true" class="anchor"></a>p</h3><ol class="packages"><li id="package-picos"><a href="#package-picos" aria-hidden="true" class="anchor"></a><a href="picos/index.html">picos</a> <span class="version"></span> <span class="synopsis"></span></li><li id="package-picos_std"><a href="#package-picos_std" aria-hidden="true" class="anchor"></a><a href="picos_std/index.html">picos_std</a> <span class="version"></span> <span class="synopsis"></span></li></ol><h3 id="name-t"><a href="#name-t" aria-hidden="true" class="anchor"></a>t</h3><ol class="packages"><li id="package-thread-local-storage"><a href="#package-thread-local-storage" aria-hidden="true" class="anchor"></a><a href="thread-local-storage/index.html">thread-local-storage</a> <span class="version"></span> <span class="synopsis"></span></li></ol></div><h2 id="by-tag"><a href="#by-tag" aria-hidden="true" class="anchor"></a>Packages by tag</h2><div class="by-tag"><nav><table></table></nav></div></div></body></html> |
Oops, something went wrong.