#垃圾回收 #gc #收集器 #分配 #指针 #rc #并发

dumpster

一个并发周期跟踪垃圾回收器

5个版本

0.2.1 2024年6月2日
0.2.0 2024年6月2日
0.1.2 2023年8月25日
0.1.1 2023年8月14日
0.1.0 2023年8月14日

#80内存管理

每月 38 次下载

MPL-2.0 许可证

140KB
2.5K SLoC

dumpster:Rust的周期跟踪垃圾回收器

dumpster 是一个Rust的周期检测垃圾回收器。它检测无法到达的分配并自动释放它们。

为什么你应该使用这个包?

简而言之,dumpster 提供了可用性、性能和灵活性的绝佳组合。

  • dumpster 的API是std的引用计数共享分配(RcArc)的直接替换。
  • 它性能非常好,并内置了线程局部和并发垃圾回收的实现。
  • 垃圾回收分配内的引用结构没有限制(引用可以指向任何方式)。
  • 使用提供的derive宏可以轻松地将自定义类型标记为可回收。
  • 你甚至可以将?Sized数据存储在垃圾回收指针中!

工作原理

dumpster 与大多数跟踪垃圾回收器不同。其他GC会跟踪一组根节点,然后可以使用这些根节点执行清理操作,确定哪些分配是可达的,哪些是不可达的。相反,dumpster 通过周期检测算法扩展了引用计数的垃圾回收(如std::rc::Rc),使其能够有效地清理自引用数据结构。

要深入了解,请查看这篇博客文章

该库包含的内容

dumpster 实际上包含两个垃圾回收器实现:模块 unsync 中的线程局部、非Send垃圾回收器和模块 sync 中的线程安全垃圾回收器。这些垃圾回收器可以安全地混合使用。

这个库还提供了一个用于创建自定义可收集类型的 derive 宏。

示例

use dumpster::{Collectable, unsync::Gc};

#[derive(Collectable)]
struct Foo {
    ptr: RefCell<Option<Gc<Foo>>>,
}

// Create a new garbage-collected Foo.
let foo = Gc::new(Foo {
    ptr: RefCell::new(None),
});

// Insert a circular reference inside of the foo.
*foo.ptr.borrow_mut() = Some(foo.clone());

// Render the foo inaccessible.
// This may trigger a collection, but it's not guaranteed.
// If we had used `Rc` instead of `Gc`, this would have caused a memory leak.
drop(foo);

// Trigger a collection. 
// This isn't necessary, but it guarantees that `foo` will be collected immediately (instead of 
// later).
dumpster::unsync::collect();

安装

要安装,只需将 dumpster 添加到您的项目依赖项中。

[dependencies]
dumpster = "0.1.2"

可选功能

dumpster 有两个可选功能:derivecoerce-unsized

derive 默认启用。它启用了 Collectable 的 derive 宏,使用户能够轻松实现自己的可收集类型。

use dumpster::{unsync::Gc, Collectable};
use std::cell::RefCell;

#[derive(Collectable)] // no manual implementation required
struct Foo(RefCell<Option<Gc<Foo>>>);

let my_foo = Gc::new(Foo(RefCell::new(None)));
*my_foo.0.borrow_mut() = Some(my_foo.clone());

drop(my_foo); // my_foo will be automatically cleaned up

coerce-unsized 默认禁用。它启用了每个垃圾回收器的 CoerceUnsized 实现,使得能够方便地使用 Gc!Sized 类型。

use dumpster::unsync::Gc;

// this only works with "coerce-unsized" enabled while compiling on nightly Rust
let gc1: Gc<[u8]> = Gc::new([1, 2, 3]);

要使用 coerce-unsized,请编辑您的 Cargo.toml 文件以包含此功能。

[dependencies]
dumpster = { version = "0.1.2", features = ["coerce-unsized"]}

许可协议

此代码受 Mozilla 公共许可证(版本 2.0)许可。有关更多信息,请参阅 LICENSE.md

依赖项

~0.4–6MB
~14K SLoC