12 个稳定版本 (3 个主要版本)

3.0.2 2024 年 8 月 11 日
3.0.1 2024 年 8 月 10 日
2.1.0 2024 年 7 月 28 日
1.7.0 2024 年 7 月 18 日
0.0.2 2024 年 4 月 14 日

#67并发

Download history 45323/week @ 2024-05-01 50268/week @ 2024-05-08 56887/week @ 2024-05-15 54259/week @ 2024-05-22 61232/week @ 2024-05-29 65942/week @ 2024-06-05 77519/week @ 2024-06-12 80243/week @ 2024-06-19 79247/week @ 2024-06-26 81988/week @ 2024-07-03 93058/week @ 2024-07-10 99228/week @ 2024-07-17 111320/week @ 2024-07-24 108667/week @ 2024-07-31 114807/week @ 2024-08-07 111781/week @ 2024-08-14

每月 466,266 次下载
329 个 Crates 中使用 (直接使用 2 个)

Apache-2.0

115KB
2K SLoC

可扩展延迟销毁

Cargo Crates.io GitHub Workflow Status

一个可扩展的无锁延迟内存回收器,通过跟踪内存可达性来模拟垃圾回收。

它的延迟销毁算法基于基于时期回收的一种变体,其中已退役的内存块存储在线程局部存储中,直到满足某些标准。crossbeam_epoch crate 提供了类似的功能,但是用户会发现 sdd 更容易使用,因为内存块的生命周期被安全地管理。例如,sdd::AtomicOwnedsdd::Owned 在它们被丢弃时退役包含的实例,而 sdd::AtomicSharedsdd::Shared 在最后一个强引用被丢弃时退役实例。

功能

  • 基于时期的无锁回收。
  • Loom 支持: features = ["loom"]

示例

此 crate 可以在 不使用 unsafe 块的情况下使用

use sdd::{suspend, AtomicOwned, AtomicShared, Guard, Owned, Ptr, Shared, Tag};
use std::sync::atomic::Ordering::Relaxed;

// `atomic_shared` holds a strong reference to `17`.
let atomic_shared: AtomicShared<usize> = AtomicShared::new(17);

// `atomic_owned` owns `19`.
let atomic_owned: AtomicOwned<usize> = AtomicOwned::new(19);

// `guard` prevents the garbage collector from dropping reachable instances.
let guard = Guard::new();

// `ptr` cannot outlive `guard`.
let mut ptr: Ptr<usize> = atomic_shared.load(Relaxed, &guard);
assert_eq!(*ptr.as_ref().unwrap(), 17);

// `atomic_shared` can be tagged.
atomic_shared.update_tag_if(Tag::First, |p| p.tag() == Tag::None, Relaxed, Relaxed);

// `ptr` is not tagged, so CAS fails.
assert!(atomic_shared.compare_exchange(
    ptr,
    (Some(Shared::new(18)), Tag::First),
    Relaxed,
    Relaxed,
    &guard).is_err());

// `ptr` can be tagged.
ptr.set_tag(Tag::First);

// The ownership of the contained instance is transferred to the return value of CAS.
let prev: Shared<usize> = atomic_shared.compare_exchange(
    ptr,
    (Some(Shared::new(19)), Tag::Second),
    Relaxed,
    Relaxed,
    &guard).unwrap().0.unwrap();
assert_eq!(*prev, 17);

// `17` will be garbage-collected later.
drop(prev);

// `sdd::AtomicShared` can be converted into `sdd::Shared`.
let shared: Shared<usize> = atomic_shared.into_shared(Relaxed).unwrap();
assert_eq!(*shared, 19);

// `18` and `19` will be garbage-collected later.
drop(shared);
drop(atomic_owned);

// `17` is still valid as `guard` keeps the garbage collector from dropping it.
assert_eq!(*ptr.as_ref().unwrap(), 17);

// Execution of a closure can be deferred until all the current readers are gone.
guard.defer_execute(|| println!("deferred"));
drop(guard);

// `sdd::Owned` and `sdd::Shared` can be nested.
let shared_nested: Shared<Owned<Shared<usize>>> = Shared::new(Owned::new(Shared::new(20)));
assert_eq!(***shared_nested, 20);

// If the thread is expected to lie dormant for a while, call `suspend()` to allow
// others to reclaim the memory.
suspend();

内存开销

已退役的实例存储在线程局部存储中的侵入式队列中,因此为每个实例分配了额外的空间 Option<NonNull<dyn Collectible>>

性能

进入和退出受保护区域的平均时间:在 Apple M2 Max 上为 2.4 纳秒。

变更日志

依赖关系

~0–24MB
~333K SLoC