21 个版本 (6 个稳定版)
1.1.2 | 2024年6月14日 |
---|---|
1.0.2 | 2024年3月10日 |
0.4.1 | 2024年1月30日 |
0.4.0 | 2023年12月19日 |
0.1.1 | 2023年3月14日 |
#122 in 编码
9,965 每月下载量
用于 serde_avro_derive
290KB
7K SLoC
serde_avro_fast
serde/avro (反)序列化的惯用实现
入门指南
let schema: serde_avro_fast::Schema = r#"
{
"namespace": "test",
"type": "record",
"name": "Test",
"fields": [
{
"type": {
"type": "string"
},
"name": "field"
}
]
}
"#
.parse()
.expect("Failed to parse schema");
#[derive(serde_derive::Deserialize, Debug, PartialEq)]
struct Test<'a> {
field: &'a str,
}
let avro_datum = &[6, 102, 111, 111];
assert_eq!(
serde_avro_fast::from_datum_slice::<Test>(avro_datum, &schema)
.expect("Failed to deserialize"),
Test { field: "foo" }
);
serde/avro (反)序列化的惯用实现
在编写本文时,其他现有的Avro (反)序列化库对于每个遇到的记录都会进行大量的不必要的分配、HashMap查找等操作。
这个版本是一个更符合习惯的实现,既适用于Rust,也适用于 serde
。
因此,性能提升了10倍以上(参见基准测试)
apache_avro/small time: [386.57 ns 387.04 ns 387.52 ns]
serde_avro_fast/small time: [19.367 ns 19.388 ns 19.413 ns] <- x20 improvement
apache_avro/big time: [1.8618 µs 1.8652 µs 1.8701 µs]
serde_avro_fast/big time: [165.87 ns 166.92 ns 168.09 ns] <- x11 improvement
它支持任何schema/反序列化目标类型组合,包括使用(或不用)枚举的高级联合使用,以及正确的Option支持。如果您有特殊用例,通常应该支持(如果不支持,请随时提出问题)。
与apache-avro的比较
除了已经提到的性能提升之外,还有一些主要的设计差异
Value
被移除了。反序列化是一个单步过程,完全集成于serde,并利用其零拷贝功能。输出结构现在可以借用源切片。- 在Rust中,中间
Value
表示形式似乎是多余的,因为Value
的两个用例似乎是这样的- 某种已知的数据结构,但仍有部分动态处理 -> 您可以将数据反序列化到相对动态的rust类型,例如HashMap、Vec...
- 基本上没有结构信息的不同序列化格式(例如JSON)的转码 -> 这可以通过使用
serde_transcode
以更高效和更符合习惯的方式实现。
- 与直接反序列化到正确的结构(尤其是当这种表示形式涉及与apache-avro相同数量的分配时)相比,
Value
表示形式会降低性能。
- 在Rust中,中间
- 已移除读取器模式概念。在 Rust 中,由于它是一种完全静态类型语言,因此这似乎是不必要的。通过 Serde 框架通过结构体提供的反序列化提示与写入器模式信息相结合,可以直接构建正确的类型,无需单独的模式。
- 我预计,任何目前使用读取器模式的代码都可以不指定读取器模式即可直接使用这个新的反序列化器。
- 如果需要将 Avro 字节流从一种模式转换为另一种模式,这很可能只需通过
serde_transcode
将反序列化器连接到序列化器即可实现,因为这样的序列化器将结合从原始结构体(或在这种情况下,反序列化器)提供的类型与模式变体,以正确的方式重新映射值,同时保留零分配。
- 模式表示已被重新设计为预计算的自我引用图结构。
- 这就是为什么在(反)序列化操作期间遍历它时可以提供最大性能的原因。
依赖项
~5–7.5MB
~142K SLoC