|
4 | 4 | [<img alt="github" src="https://img.shields.io/badge/github-seize-blue?style=for-the-badge" height="25">](https://github.com/ibraheemdev/seize) |
5 | 5 | [<img alt="docs.rs" src="https://img.shields.io/docsrs/seize?style=for-the-badge" height="25">](https://docs.rs/seize) |
6 | 6 |
|
7 | | -Fast, efficient, and robust memory reclamation for concurrent data structures. |
| 7 | +Fast, efficient, and predictable memory reclamation for concurrent data |
| 8 | +structures. |
8 | 9 |
|
9 | | -See the [quick-start guide] to get started. |
| 10 | +Refer to the [quick-start guide] to get started. |
10 | 11 |
|
11 | 12 | ## Background |
12 | 13 |
|
13 | 14 | Concurrent data structures are faced with the problem of deciding when it is |
14 | | -safe to free memory. Although an object might have been logically removed, other |
15 | | -threads that previously loaded it may still be accessing it, and thus it is |
| 15 | +safe to free memory. Despite an object being logically removed, it may still be |
| 16 | +accessible by other threads that are holding references to it, and thus it is |
16 | 17 | not safe to free immediately. Over the years, many algorithms have been devised |
17 | 18 | to solve this problem. However, most traditional memory reclamation schemes make |
18 | | -the tradeoff between performance, efficiency, and robustness. For example, |
19 | | -[epoch based reclamation] is fast and lightweight but lacks robustness in that a |
20 | | -stalled thread can prevent the reclamation of _all_ retired objects. [Hazard |
21 | | -pointers], another popular scheme, tracks individual pointers, making it efficient |
22 | | -and robust but generally much slower. |
| 19 | +a tradeoff between performance and efficiency. |
23 | 20 |
|
24 | | -Another problem that is often not considered is workload balancing. In most |
25 | | -reclamation schemes, the thread that retires an object is the one that reclaims |
26 | | -it. This leads to unbalanced reclamation in read-dominated workloads; parallelism |
27 | | -is reduced when only a fraction of threads are writing, degrading memory efficiency. |
| 21 | +For example, [hazard pointers] track individual pointers, making them very |
| 22 | +memory efficient but also relatively slow. On the other hand, [epoch based |
| 23 | +reclamation] is fast and lightweight, but lacks predictability, requiring |
| 24 | +periodic checks to determine when it is safe to free memory. This can cause |
| 25 | +reclamation to trigger unpredictably, leading to poor latency distributions. |
28 | 26 |
|
29 | | -## Implementation |
| 27 | +Alternative epoch-based schemes forgo workload balancing, relying on the thread |
| 28 | +that retires an object always being the one that frees it. While this can avoid |
| 29 | +synchronization costs, it also leads to unbalanced reclamation in read-dominated |
| 30 | +workloads; parallelism is reduced when only a fraction of threads are writing, |
| 31 | +degrading memory efficiency as well as performance. |
30 | 32 |
|
31 | | -seize is based on the [hyaline reclamation scheme], which uses reference counting |
32 | | -to determine when it is safe to free memory. However, reference counters are only |
33 | | -used for already retired objects, allowing it to avoid the high overhead incurred |
34 | | -by traditional reference counting schemes where every memory access requires modifying |
35 | | -shared memory. Reclamation is naturally balanced as the thread with the last reference |
36 | | -to an object is the one that frees it. This removes the need to check whether other |
37 | | -threads have made progress, leading to predictable latency without sacrificing performance. |
38 | | -Epochs can also be tracked to protect against stalled threads, making reclamation truly |
39 | | -lock-free. |
| 33 | +## Implementation |
40 | 34 |
|
41 | | -seize provides performance competitive with that of epoch based schemes, while memory efficiency |
42 | | -is similar to that of hazard pointers. seize is compatible with all modern hardware that |
43 | | -supports single-word atomic operations such as FAA and CAS. |
| 35 | +`seize` is based on the [hyaline reclamation scheme], which uses reference |
| 36 | +counting to determine when it is safe to free memory. However, unlike |
| 37 | +traditional reference counting schemes where every memory access requires |
| 38 | +modifying shared memory, reference counters are only used for retired objects. |
| 39 | +When a batch of objects is retired, a reference counter is initialized and |
| 40 | +propagated to all active threads. Threads cooperate to decrement the reference |
| 41 | +counter as they exit, eventually freeing the batch. Reclamation is naturally |
| 42 | +balanced as the thread with the last reference to an object is the one that |
| 43 | +frees it. This also removes the need to check whether other threads have made |
| 44 | +progress, leading to predictable latency without sacrificing performance. |
| 45 | + |
| 46 | +`seize` provides performance competitive with that of epoch based schemes, while |
| 47 | +memory efficiency is similar to that of hazard pointers. `seize` is compatible |
| 48 | +with all modern hardware that supports single-word atomic operations such as FAA |
| 49 | +and CAS. |
44 | 50 |
|
45 | 51 | [quick-start guide]: https://docs.rs/seize/latest/seize/guide/index.html |
46 | | -[tokio]: https://github.com/tokio-rs/tokio |
47 | 52 | [hazard pointers]: |
48 | 53 | https://www.cs.otago.ac.nz/cosc440/readings/hazard-pointers.pdf |
49 | 54 | [hyaline reclamation scheme]: https://arxiv.org/pdf/1905.07903.pdf |
|
0 commit comments