#垃圾收集 #gc #derive #dumpster

dumpster_derive

为dumpster实现#[derive(Collectable)]

3 个不稳定版本

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

#70 in #gc


用于 dumpster

MPL-2.0 许可证

13KB
145

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

依赖项

~275–720KB
~17K SLoC