3 个版本 (破坏性更新)
0.3.0 | 2024 年 7 月 6 日 |
---|---|
0.2.0 | 2024 年 7 月 4 日 |
0.1.0 | 2024 年 7 月 4 日 |
#76 在 缓存
每月 248 次下载
36KB
625 行
interned-string
此存储库公开 IString
,一种不可变且已缓存的字符串类型。
它为高性能和考虑多线程而构建。
它提供了 O(1) 的 Hash
和 Eq
操作,非常适合您的 HashMap<IString, _>
。
入门指南
您可以通过调用 intern()
来缓存任何 String
或 &str
值。
您可以将 IString
通过引用传递给任何接受 &str
的函数。
use interned_string::Intern;
fn main() {
let my_istring = "hello".intern();
foo(&my_istring);
}
fn foo(string: &str) {
println!("{string}");
}
如果您启用了 serde
功能,您可以在您的 DTO 中使用 IString
代替 String
。
[dependencies]
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
interned-string = { version = "0.1", features = ["serde"] }
use serde::Deserialize;
use interned_string::IString;
#[derive(Deserialize, Debug)]
struct ExampleDTO {
favorite_dish: IString
}
fn main() {
let serialized = "{\"favorite_dish\":\"pasta\"}";
let example: ExampleDTO = serde_json::from_str(&serialized).unwrap();
println!("{example:?}")
// ExampleDTO { favorite_dish: IString("pasta") }
}
性能特点
读取 IString
的内容非常快,无锁且无等待(归功于 left_right
)。IString
可以在任意数量的线程中共享和读取。它可以随着读取线程数量的线性增长而扩展。
代价是创建一个新的 IString
会更慢。需要遍历基数树(紧凑前缀树)以去重新字符串,需要获取锁,如果字符串尚未缓存,则需要更新树。虽然可以从多个线程并行执行树遍历,但锁阻止了写入的线性扩展。
计划改进
-
用可重用字符串存储的基数树或重新编写它,而不是在基数树中存储每个已缓存字符串的副本。目前,由于这个原因,存储库使用了 2 倍的已缓存字符串存储空间(1 倍在存储中,1 倍作为基数树中的副本)。
-
在后台/冷路径中释放未使用字符串的内存。目前内存仅在存储中插入新字符串时才会释放,这可能会令人意外。
贡献
欢迎您提交PR。任何贡献都将被高度赞赏。
如果您有建议,请提交Issue。
许可
致谢
特别感谢Jon Gjengset (@jonhoo) 为此crate提供灵感,以及他对 left-right
的工作。
依赖
~0.8–27MB
~343K SLoC