比 Go 慢 5 倍?优化 Rust Protobuf 解码性能

主要观点:在优化 GreptimeDB v0.7 的写入性能时,发现解析 Prometheus 写入请求的 CPU 时间占比约 12%,Go 实现的 VictoriaMetrics 协议解析 CPU 时间约 5%,从而开始考虑优化协议转换层开销。通过一系列实验和优化,如采用RepeatedField、调整BytesString类型、优化Bytes::slice等操作,将解析单个 WriteRequest 的时间从 Rust 的约 7.3ms 降低到约 1.6ms,接近 Go 的 1.2ms。
关键信息

  • 提供了优化代码的 GitHub 仓库https://github.com/v0y4g3r/prom-write-request-bench
  • 介绍了不同步骤的优化方法及对应的代码和结果,如采用RepeatedField将处理时间降至约 36%,调整BytesString类型导致性能下降,优化Bytes::slice后性能提升等。
  • 提及 Rust 直接操作字节数组时的内存安全限制及Bytes的效率问题,通过unsafe方法绕过Bytes的引用计数机制。
  • 还介绍了 GreptimeDB 在写入路径的其他优化工作,如消除中间结构、切换 HashMap 等。
    重要细节
  • Go 版本通过设置WriteRequestTimeseries字段为空切片来实现对象复用,避免重复内存分配;Rust 版本最初在每次反序列化时创建新结构,后通过RepeatedField机制优化。
  • 在将LabelString字段改为Bytes类型时,发现Bytes::copy_to_bytes操作带来额外开销,通过专门化类型消除该开销。
  • Bytes::slice操作进行性能测试,发现 Rust 中该操作比 Go 慢约两个数量级,原因包括引用计数机制、vtable 动态调度和边界检查等。
  • 通过unsafe方法优化Bytes的切片操作,将时间从 103us 降低到 24us,最终将解析时间降至约 1.6ms。
  • 介绍了 Greptime 的相关产品和解决方案,如 GreptimeDB、GreptimeCloud 和 Edge-Cloud Integrated Solution 等,并鼓励参与 GitHub 和 Slack 社区。
阅读 12
0 条评论