6 个版本
0.2.0 | 2024年5月27日 |
---|---|
0.1.4 | 2024年4月11日 |
0.1.3 | 2023年11月20日 |
0.1.2 | 2023年10月30日 |
#230 在 编码
2,754 每月下载量
用于 sql-json-path
105KB
2K SLoC
jsonbb
jsonbb
是 JSON 值的二进制表示,灵感来自 PostgreSQL 中的 JSONB,并优化于快速解析。
用法
jsonbb
提供与 serde_json
相似的 API,用于构建和查询 JSON 值。
// Deserialize a JSON value from a string of JSON text.
let value: jsonbb::Value = r#"{"name": ["foo", "bar"]}"#.parse().unwrap();
// Serialize a JSON value into JSON text.
let json = value.to_string();
assert_eq!(json, r#"{"name":["foo","bar"]}"#);
作为一个二进制格式,你可以从中提取字节切片,或者从字节切片中读取 JSON 值。
// Get the underlying byte slice of a JSON value.
let jsonbb = value.as_bytes();
// Read a JSON value from a byte slice.
let value = jsonbb::ValueRef::from_bytes(jsonbb);
你可以使用常见的 API 查询 JSON,然后使用 Builder
API 构建新的 JSON 值。
// Indexing
let name = value.get("name").unwrap();
let foo = name.get(0).unwrap();
assert_eq!(foo.as_str().unwrap(), "foo");
// Build a JSON value.
let mut builder = jsonbb::Builder::<Vec<u8>>::new();
builder.begin_object();
builder.add_string("name");
builder.add_value(foo);
builder.end_object();
let value = builder.finish();
assert_eq!(value.to_string(), r#"{"name":"foo"}"#);
格式
jsonbb
在连续内存中存储 JSON 值。通过避免动态内存分配,它更加缓存友好,并提供高效的 解析 和 查询 性能。
它具有以下关键特性
- 内存连续性:任何 JSON 子树的 内容都连续存储,允许通过
memcpy
进行高效的复制。这导致了非常高效的索引操作。 - 后序遍历:JSON 节点按后序遍历顺序存储。当解析 JSON 字符串时,输出可以顺序写入缓冲区,无需额外的内存分配和移动。这导致了非常高效的解析操作。
性能比较
item[^0] | jsonbb | jsonb | serde_json | simd_json |
---|---|---|---|---|
canada.parse() |
4.7394 ms | 12.640 ms | 10.806 ms | 6.0767 ms [^1] |
canada.to_json() |
5.7694 ms | 20.420 ms | 5.5702 ms | 3.0548 ms |
canada.size() |
2,117,412 B | 1,892,844 B | ||
canada["type"] [^2] |
39.181 ns[^2.1] | 316.51 ns[^2.2] | 67.202 ns [^2.3] | 27.102 ns [^2.4] |
citm_catalog["areaNames"] |
92.363 ns | 328.70 ns | 2.1190 µs [^3] | 1.9012 µs [^3] |
from("1234567890") |
26.840 ns | 91.037 ns | 45.130 ns | 21.513 ns |
a==b |
66.513 ns | 115.89 ns | 39.213 纳秒 | 41.675 纳秒 |
a<b |
71.793 纳秒 | 120.77 纳秒 | 不支持 | 不支持 |
[^0]:基准测试的 JSON 文件:canada,citm_catalog
[^1]:解析为 simd_json::OwnedValue
以确保公平。
[^2]:canada["type"]
返回一个字符串,因此该操作的主要开销在于索引。
[^2.1]:jsonbb
使用二分搜索对排序键进行搜索 [^2.2]:jsonb
使用线性搜索对未排序键进行搜索 [^2.3]:serde_json
使用 BTreeMap
[^2.4]:simd_json
使用 HashMap
[^3]:citm_catalog["areaNames"]
返回一个包含 17 个键值字符串对的对象。然而,由于每个字符串都进行动态内存分配,serde_json
和 simd_json
的性能较慢。相比之下,jsonb 采用平面表示,允许直接进行memcpy操作,从而提高性能。
依赖项
~0.7–2.3MB
~43K SLoC