5个版本
0.8.0 | 2021年12月8日 |
---|---|
0.7.3 | 2021年12月3日 |
0.7.2 | 2021年11月25日 |
0.7.1 | 2021年11月25日 |
0.7.0 | 2021年11月21日 |
#281 in 压缩
每月32次下载
575KB
12K SLoC
Docchi是一种基于差异的数据管理语言,用于实现无限撤销、游戏的自动保存以及需要频繁保存更改的云应用。
Docchi是一种语言,因此API文档并不适合学习。你可能需要阅读用户手册。
- Rust支持的最小版本
1.57.0(稳定版)
- 演示
测试数据
{
"data0": "oiufsjdsj...", //1 MB of random string
"data1": "abuisoehg...", //1 MB of random string
//...
"data9": "bhsiofdis...", //1 MB of random string
}
伪代码
for i in 0..100{
modify_one_string(json.get_data_mut(rand.gen_range(0..10)));
let s = serde_json::to_string(&json);
let mut file = std::fs::File::create(format!("{}/d{}.json", json_dir, i))?;
file.write_all(s.as_bytes())?;
}
JSON包含十个随机的1 MB字符串,因此整个JSON文件约为10 MB。
我们一次修改一个字符串,并以JSON格式保存,重复了100次。文件总数约为1 GB。
这意味着每次修改了10%的数据。数据通常只部分修改,因此10%并不是非常不常见。
相当于Docchi数据被创建、修改和保存了100次。
Docchi只保存"差异"。在最理想的情况下,只保存1 MB的修改数据。
结果如下
JSON
sum of file sizes 1021435957
1906 milliseconds
Docchi
sum of file sizes 173005171
604 milliseconds
JSON保存了约1 GB的数据,耗时1906毫秒。
Docchi保存了约173 MB的数据,耗时604毫秒。
Docchi只占用了17%的存储空间,约三分之一的时间。
怎么样?
Docchi只保存了17%的数据,所以当然更快。
为了比较,我们将JSON字符串的长度改为17%,然后运行演示。
JSON(short)
sum of file sizes 173570901
338 milliseconds
文件大小大致相同,JSON比Docchi快两倍。
Serde非常快,因此结果是合理的。
但我认为Docchi的开销是合理的,Docchi可以以非阻塞方式保存,因此保存时间可能不会降低用户体验。
*加载演示
加载是Docchi付出代价的地方。Docchi创建"差异层次结构"。
Diff Hierarchy Concept
Diff0(10 MB) - Diff00(1 MB) - Diff000(1 MB)
│
Diff001(1 MB)
│
Diff002(1 MB)
- Diff01(5 MB) - Diff010(1 MB)
│
Diff011(1 MB)
│
Diff012(1 MB)
...
- Diff02(10 MB)- Diff020(1 MB)
│
Diff021(1 MB)
...
...
Diff1(10 MB)
...
要加载Docchi的差异,我们必须从顶部到底部按层次加载文件,并重复应用差异。
我们使用了Docchi的默认设置,最多需要13个文件来加载一个数据。
要加载的总文件大小可以是最大差异文件(在这种情况下为10 MB)的四倍,因此为40 MB。
我们从层次结构中搜索最深的文件并加载数据。
Docchi
40 milliseconds
JSON
94 milliseconds
JSON(Short)
16 milliseconds
Docchi 的数据总量是 JSON 的 4 倍,但比 JSON 快超过 2 倍。
Docchi 是一种二进制数据格式,并且高效地多线程加载,所以它能够击败 Serde,我想。
* 如何做到这一点?
构造差异是一个成本很高的自然过程,但 Rust 的 Arc(原子引用计数指针)使它变得非常简单。
Docchi 的数据在保存时被克隆,因此可以进行非阻塞保存。Docchi 的数据由 Arc 组成,所以克隆可以瞬间完成。
使用 Arc::make_mut,当两个不同的 Arc 指向同一对象并且其中一个被修改时,实际上会发生内部数据的复制。当它被修改时,两个 Arc 指向不同的对象,所以比较两个 Arc 指针的指针就足够确认是否被修改。比较实际值是不必要的。
实际复制发生在实际要修改的部分。复制一切也是不必要的。Rust 的 Arc 真的是神奇的。
在比较数据和构造差异时,我们比较当前对象与保存时克隆的对象,并比较指针。这是一个非常快速的过程。
另一方面,我们在加载时没有做任何特别的事情。如果它很快,那要归功于 Rayon。
许可证
根据您的选择,许可权为以下之一
- Apache License,版本 2.0,(LICENSE-APACHE 或 http://www.apache.org/licenses/LICENSE-2.0)
- MIT 许可证 (LICENSE-MIT 或 http://opensource.org/licenses/MIT)
自行决定。
贡献
除非您明确表示,否则根据 Apache-2.0 许可证定义的,您有意提交的任何贡献,包括在本工作中,将如上所述双重许可,没有任何额外的条款或条件。
我非常期待有人能
- 纠正我的英语(我不是英语母语者)
- 批评我的代码/API
依赖关系
~8MB
~151K SLoC