39 次发布
0.8.4 | 2024年6月22日 |
---|---|
0.7.5 | 2024年4月10日 |
0.7.4 | 2023年10月28日 |
0.7.1 | 2023年6月18日 |
0.3.4 | 2018年2月27日 |
#10 in 缓存
110,964 每月下载量
在 161 个 Crates 中使用 (10 个直接使用)
110KB
2.5K SLoC
Internment —
一个用于在 Rust 中归一化字符串或其他数据的非常容易使用的库。归一化数据在哈希或比较等价性(只是指针比较)方面非常高效。数据也会自动去重。
使用 internment crate 有三种选择
-
Intern
,它永远不会释放你的数据。这意味着Intern
是Copy
,所以你可以免费制作尽可能多的指针副本。其实现也不使用不安全代码。 -
ArcIntern
,它引用计数你的数据,当没有更多引用时释放它。ArcIntern
将保持内存使用量低,但在创建你的指针副本或丢弃指针时使用原子递增/递减。需要功能arc
。 -
ArenaIntern
,它在Arena
中存储其数据,当释放 arena 本身时释放数据。需要功能arena
。
在每种情况下,访问你的数据都是一个指针解引用,任何归一化数据结构(Intern
或 ArcIntern
或 ArenaIntern
)的大小都是一个指针。在每种情况下,你都有保证单个数据值(由 Eq
和 Hash
定义)将对应单个指针值。这意味着我们可以使用指针比较(和指针哈希)来代替值比较,这非常快。
此外,请注意,如果您不使用 Intern
类型,您可能希望使用以下命令编译:cargo build --no-default-features --features arc
(或 arena
),这将略微加快您的构建速度并减小可执行文件的大小。
示例
use internment::Intern;
let x = Intern::new("hello");
let y = Intern::new("world");
assert_ne!(x, y);
println!("The conventional greeting is '{} {}'", x, y);
Arena 示例
use internment::Arena;
let arena: Arena<&'static str> = Arena::new();
let x = arena.intern("hello");
let y = arena.intern("world");
assert_ne!(x, y);
println!("The conventional greeting is '{} {}'", x, y);
与其他 Intern 库的比较
在 crates.io 上已经有一些可用的 Intern 库。那么 internment
有什么不同之处?许多 Intern 库都是特定于字符串的。通用目的的 Intern 库包括:
这些库都实现了 arena 分配,使用各种大小的令牌来引用 interned 对象。这种方法使得它们的使用远比 internment
更具挑战性。它们的方法还允许在超出作用域时一次性释放所有 interned 对象(这是一个优点)。
相对于 internment
的方法,arena 分配的主要缺点是:
-
令牌的查找可能会失败,这可能是因为手动生成无效的令牌,或者一个池中的令牌被另一个池使用。这给使用 interned 对象的代码添加了一个不安全因素:要么它们假设没有错误并遇到错误时崩溃,要么它们在所有使用令牌的地方都有错误处理。
-
如果使用多个池,令牌的查找可能会给出错误的对象。如果您避免使用多个池,这很容易避免,但您可能不会从 arena 分配中获得太多好处。
-
令牌的查找速度较慢。虽然它们都宣传速度快,但任何查找都将比指针解引用慢。公平地说,增加内存局部性原则上可能在某些访问模式中使令牌查找更快,但我怀疑这一点。
为了平衡这一点,因为 internment
有全局有效的令牌,它使用一个 Mutex
来保护其内部数据,在 intern 新数据时进行,这可能比其他 intern 库慢(除非您想要在线程间使用它们的令牌,在这种情况下,您必须将池放入 Mutex
中并支付相同的代价)。
另一个与 internment
非常相似的 Intern 库是:
hashconsing
库在 API 上比 internment
更复杂,但以类似的方式生成全局指针。数据类型 HConsed<T>
总是使用 Arc
进行引用计数,这使得它与 ArcIntern
类似,但效率低于 Intern
,但不会永久泄漏内存。
依赖项
~1.4–7MB
~41K SLoC