5 个版本
使用旧的 Rust 2015
0.1.4 | 2020年9月4日 |
---|---|
0.1.3 | 2017年8月31日 |
0.1.2 | 2017年8月31日 |
0.1.1 | 2017年8月30日 |
0.1.0 | 2017年8月30日 |
#382 in 内存管理
28KB
521 行
rust-obstack
一个快速的分段栈分配器,支持任何类型的多个对象。
一种类型的竞技场分配器,obstacks 在 Obstack
本身被销毁时一次性释放内存。其优点是分配速度极快:只需指针增加。与类型化的竞技场不同,单个 Obstack
可以包含具有任何数量不同类型的值。
对于 Copy
类型,将值推送到 Obstack
返回一个标准的可变引用
let r: &mut u8 = stack.push_copy(42);
assert_eq!(*r, 42);
Copy
类型不能实现 Drop
,因此不需要进行任何操作来释放值,除了释放内存本身,这在 Obstack
本身被丢弃时一次性完成。push_copy()
因此仅限于实现 Copy
的类型。
未实现 Copy
的类型 可能 实现 Drop
。由于 Rust 的类型系统没有负的 !Drop
特性,Obstack
有第二个方法 - push()
- 不会限制在 Copy
类型上。此方法返回包装类型 Ref<T>
,它包装了底层的可变引用。此包装器拥有栈上的值,并确保当包装器超出作用域时调用 drop
。基本上 Ref
是 Box
的等价物,但使用 Obstack
而不是堆。
在实践中,即使使用了 Ref
包装器,如果底层类型实际上没有实现有意义的 drop
方法,Rust 编译器能够优化掉所有对 drop
的调用,从而获得与 Copy
类型相同的性能;实际的 Ref::drop()
方法是 [inline(always)]
,以帮助这个过程。这很重要,因为并非所有非 Copy
类型都可以实现 - 尤其是可变引用不能。
Obstack
以分段栈的形式分配内存,由一个或多个连续内存段组成。每次顶部段满了,就会从堆中分配一个新的段。为了确保总分配数保持很小,段以2的幂次形式分配,每个段的大小是前一个的两倍。
一旦分配了段,它就会在整个 Obstack
生命周期中保持稳定,允许直接引用该段中的值;Rust 的生命周期确保这些引用在 Obstack
的生命周期内有效。
基准测试
可以使用以下命令运行一些初步的基准测试:
cargo bench
tl;dr:分配和释放链表的速度大约快10倍。