#protobuf #deserialize #serialization #wire-format

rustwire

一个用于高效操作编码的协议缓冲区消息的Rust库

3 个不稳定版本

0.2.0 2024年5月17日
0.1.0 2024年5月14日

#1326 in 编码

MIT 许可证

51KB
885

Rustwire

Latest Version docs.rs

一个专门用于解码和操作Protobuf编码消息的Rust库。

这是一个无依赖的辅助包,并不打算成为一个完整的Protobuf库。它旨在与像prostprotobuf这样的完整Protobuf库一起使用。例如,我们使用它的主要用例是从嵌套的Protobuf中提取内容,并用该嵌套Protobuf的ID替换它们。

什么是Rustwire?

  • 快速:Rustwire设计得尽可能快,因为它不会解码整个消息。
  • 轻量级:Rustwire是一个没有依赖项的小型库。

Rustwire不是什么?

  • 完整的Protobuf库:Rustwire不是设计为完整的Protobuf库。它旨在与像prostprotobuf这样的完整Protobuf库一起使用。

  • protobuf兼容性变更集工具:Rustwire的主要用例是替换嵌套的Protobuf消息。Rustwire不会检查你对该消息所做的更改是否有效,它只是用新字段替换字段。

组件

Rustwire由三个主要组件组成

  • 提取器:提取器用于从Protobuf编码的消息中提取字段。
  • 替换器:替换器用于替换Protobuf编码的消息中的字段。
  • 编码器:编码器用于将字段编码到Protobuf编码的消息中。这主要用于varint字段。

速度

这个库被设计为尽可能快地操作编码的消息,因此无需解码。为了理解这种影响,我们创建了三个基准测试(所有基准测试都是从一个消息中读取一个字段)

读取

基准测试 Rustwire Prost
11字节 62纳秒 83纳秒
75字节 207纳秒 240纳秒
4k字节 63纳秒 488纳秒

这种性能主要来自于Rustwire不会解码不感兴趣的字段,而Prost会。这意味着当您只需要从消息中读取几个字段时,Rustwire会更快。

写入

在这个基准测试中,我们假设我们有一个名为ThisMessage的消息,其结构如下

message ThisMessage {
    int32 field1 = 1;
    string field2 = 2;
    uint64 field3 = 3;
    bool field4 = 4;
    User user = 5;
}

用户消息具有以下结构:

message User {
    string name = 1;
    int32 id = 2;
    string email = 3;
}

假设我们有很多ThisMessage消息,但只有很少的User消息。Protobuf是一种二进制格式,可以很容易地用于在数据库中存储数据。为了优化存储空间,我们希望用仅包含id字段的User消息来替换User消息。要在Prost中做到这一点,您需要:

  1. 创建一个只包含id字段的新消息,而不是User消息。
编码后的消息(点击展开)
message OutMessage {
    int32 field1 = 1;
    string field2 = 2;
    uint64 field3 = 3;
    bool field4 = 4;
    int32 user_id = 5;
}
  1. 解码ThisMessage消息,然后提取User消息并将其替换为id字段。
  2. 重新编码新消息。

在我们的基准测试中,这花费了532 ns

在Rustwire中,您可以:

  1. ThisMessage消息中提取User消息。
let user_field = extract_field_by_tag(encoded_message, 5).unwrap();
let id = extract_field_by_tag(&user_field, 2).unwrap();
  1. 创建一个只包含id字段的新消息。
let header = create_header(5, Variant::Varint.into(), &id);
let replace_with = [header, id].concat();
  1. id字段替换User消息。
let result = replace_field_with(&mut encoded_message.to_vec(), 5, &replace_with).unwrap();

这花费了31 ns

许可证

本项目采用MIT许可证 - 详细内容请参阅LICENSE文件。

无运行时依赖