2 个版本

0.1.1 2023年12月16日
0.1.0 2023年12月2日

#495内存管理

MIT 许可证

21KB
256

ref_arena

A no_std (alloc) 池,其行为类似于 Slab<Rc<T>>,但性能更好且功能更少。

此池将引用计数与对象存储在连续的缓冲区中,这减少了多次小内存分配的需求。引用可以被克隆,并像正常的 Rc 一样操作。当所有指向对象的引用都释放后,空间将可用于新的对象,并且如果池被释放,底层的缓冲区也可能被释放。

此池具有恒定时间插入、解引用和删除功能,在分配较少的情况下降低内存碎片,提高了性能(取决于分配器),并可能使用更少的内存。

RefArena 不支持弱引用,并且在未来可能不会支持。

此库使用了相当数量的不安全代码,并部分通过 miri 进行测试。由于代码不是太复杂,应该是安全的,但请注意潜在的错误。

示例

use ref_arena::{RefArena, RcRef};

let mut arena: RefArena<i32> = RefArena::new();

// Create a reference
let reference: RcRef<i32> = arena.insert(5);

// Deref to get the inner value
let inner = *reference;
assert_eq!(inner, 5);

// We can create clones of the reference just like an Rc!
let clone = reference.clone();
assert_eq!(*clone, 5);

// References can be held even after the arena is dropped.
drop(arena);
assert_eq!(*reference, 5);

// Objects (and internal buffers) are dropped when
// all references are dropped.
drop(reference);
drop(clone);

基准测试

注意:这些基准测试非常具体,旨在创建大量小型对象。

此外,这些基准测试可能会因系统和分配器而异。

分配 10k 个 Rc

std::rc::Rc   allocate 10_000  247.59 μs
RefArena      allocate 10_000  48.57 μs

~5x speedup

解引用 10k 个 Rc

std::rc::Rc   deref 10_000     4.97 μs
RefArena      deref 10_000     4.86 μs

no speedup

解引用应该在两者之间大约相同,因为它是一个简单的指针解引用。

释放 10k 个 Rc

std::rc::Rc   drop 10_000      134.35 μs
RefArena      drop 10_000      29.06 μs

~4.62x speedup

重新分配 10k 个 Rc

RefArena      realloc 10_000   45.62 μs

在这种情况下,10k 个 RcRef 被分配和释放,我们测量将 10k 个对象放回池中所需的时间。(与分配进行比较)

rc_arena 的比较

rc_arenaref_arena 类似,因为它们都是返回引用计数的池。两者都包含内部缓冲区,其中包含对象的连续列表。

两者之间的主要区别在于 rc_arena 不单独计数对象。当 ref_arena 中的对象的所有引用都释放时,内部对象将被释放,空间将可用于新的插入(类似于 slabstable-vec),而在 rc_arena 中,空间永远不会再次可用。

rc_arena在需要引用计数的对象数量确定时非常有用,而ref_arena在频繁创建和删除对象时更为适用。

请注意,这个比较可能并不完全准确,因为这仅是从代码和文档中能得知的信息。此外,这个crate并非专门为rc_arena而制作的。

许可证:MIT

无运行时依赖