推广一下支持 proto3 的 protobuf 生成工具,欢迎来找虫

343 天前
 ybilly

失业在家,把原来用到的 protobuf 工具代码整理了一下,发个支持 proto3 的生成工具,目前只支持 proto3 格式 生成的 Marshal 、MarshalTo 和 Unmarshal 方法参考 gogoprotobuf 的实现。

地址:https://github.com/billyplus/fastproto

Marshal message

    msg := &pb.SomeProtoMsg{}
    if err := fastproto.Marshal(msg); err!=nil {}

    // 预告分配好空间
    data := make([]byte, msg.Size())
    if n, err := fastproto.MarshalTo(data, msg); err!=nil {}
    // 可以用 data[:n]获取结果

Unmarshal message

    msg := &pb.SomeProtoMsg{}
    if err := fastproto.Unmarshal(data, &msg); err!=nil {}

性能对比

提升有 30%到 70%

goos: linux
goarch: amd64
pkg: github.com/billyplus/fastproto/test
cpu: AMD Ryzen 9 5950X 16-Core Processor            
  |                                  |          |              |            |                |
  | -------------------------------- | -------- | ------------ | ---------- | -------------- |
  | **FastMarshalStringSlice-6**     | 14644707 | 81.75 ns/op  | 80 B/op    | 1 allocs/op    |
  | StandardMarshalStringSlice-6     | 8223910  | 144.4 ns/op  | 80 B/op    | 1 allocs/op    |
  | **FastMarshalBytesSlice-6**      | 13065022 | 93.40 ns/op  | 80 B/op    | 1 allocs/op    |
  | StandardMarshalBytesSlice-6      | 10043254 | 124.9 ns/op  | 80 B/op    | 1 allocs/op    |
  | **FastMarshalInt32Slice-6**      | 5772819  | 213.1 ns/op  | 128 B/op   | 1 allocs/op    |
  | StandardMarshalInt32Slice-6      | 5056791  | 237.5 ns/op  | 128 B/op   | 1 allocs/op    |
  | **FastMarshalSint64Slice-6**     | 4123633  | 288.3 ns/op  | 224 B/op   | 1 allocs/op    |
  | StandardMarshalSint64Slice-6     | 3811389  | 311.4 ns/op  | 224 B/op   | 1 allocs/op    |
  | **FastMarshalSfixed32Slice-6**   | 16257074 | 73.97 ns/op  | 112 B/op   | 1 allocs/op    |
  | StandardMarshalSfixed32Slice-6   | 12917850 | 93.63 ns/op  | 112 B/op   | 1 allocs/op    |
  | **FastMarshalSfixed64Slice-6**   | 14003510 | 89.69 ns/op  | 208 B/op   | 1 allocs/op    |
  | StandardMarshalSfixed64Slice-6   | 11058189 | 115.9 ns/op  | 208 B/op   | 1 allocs/op    |
  | **FastMarshalToMixedProto-6**    | 74734    | 15354 ns/op  | 0 B/op     | 0 allocs/op    |
  | **FastMarshalMixedProto-6**      | 43844    | 27804 ns/op  | 18432 B/op | 1 allocs/op    |
  | StandardMarshalMixedProto-6      | 12552    | 94428 ns/op  | 37664 B/op | 1521 allocs/op |
  | **FastSizeMixedProto-6**         | 205432   | 6061 ns/op   | 0 B/op     | 0 allocs/op    |
  | StandardSizeMixedProto-6         | 32412    | 39230 ns/op  | 9616 B/op  | 760 allocs/op  |
  | **FastUnmarshalStringSlice-6**   | 4322337  | 291.3 ns/op  | 314 B/op   | 7 allocs/op    |
  | StandardUnmarshalStringSlice-6   | 3088686  | 384.5 ns/op  | 314 B/op   | 7 allocs/op    |
  | **FastUnmarshalBytesSlice-6**    | 3194150  | 376.0 ns/op  | 448 B/op   | 8 allocs/op    |
  | StandardUnmarshalBytesSlice-6    | 2770154  | 426.6 ns/op  | 448 B/op   | 8 allocs/op    |
  | **FastUnmarshalInt32Slice-6**    | 6377149  | 183.2 ns/op  | 112 B/op   | 1 allocs/op    |
  | StandardUnmarshalInt32Slice-6    | 3752682  | 318.7 ns/op  | 248 B/op   | 5 allocs/op    |
  | **FastUnmarshalSint64Slice-6**   | 4416526  | 271.5 ns/op  | 208 B/op   | 1 allocs/op    |
  | StandardUnmarshalSint64Slice-6   | 2903524  | 405.0 ns/op  | 504 B/op   | 6 allocs/op    |
  | **FastUnmarshalSfixed32Slice-6** | 14313001 | 85.07 ns/op  | 112 B/op   | 1 allocs/op    |
  | StandardUnmarshalSfixed32Slice-6 | 5353230  | 224.2 ns/op  | 248 B/op   | 5 allocs/op    |
  | **FastUnmarshalSfixed64Slice-6** | 12808696 | 103.0 ns/op  | 208 B/op   | 1 allocs/op    |
  | StandardUnmarshalSfixed64Slice-6 | 3824290  | 317.3 ns/op  | 504 B/op   | 6 allocs/op    |
  | **FastUnmarshalMixedProto-6**    | 20580    | 58110 ns/op  | 46909 B/op | 606 allocs/op  |
  | StandardUnmarshalMixedProto-6    | 8949     | 132525 ns/op | 60842 B/op | 1966 allocs/op |
1178 次点击
所在节点    Go 编程语言
6 条回复
FrankAdler
343 天前
支持造轮子,但是我不用,我讨厌 protobuf 。
millken
342 天前
是否支持 tinygo 下的编译,google 自己的大量使用了 reflect ,在 tinygo 下不能用。gogoprotobuf 的需要自己改动部分代码可以在 tinygo 下使用。
ybilly
342 天前
@millken 现在这个工具只是在 google 自己的.pb.go 文件之外,额外生成 marshal 、marshalto 、unmarshal 几个方法。结构的定义还是依赖于 google 的.pb.go 文件。
mcfog
342 天前
ybilly
342 天前
@mcfog 先去瞄一眼
ybilly
341 天前
@mcfog 我看了下,vtprotobuf 生成出来的代码和 gogoprotobuf 生成出来的代码一样的,而 fastproto 也是参考的 gogoprotobuf ,不过生成出来的代码重新成引用 google 的 protowire 这个包来读写数据。所以两者在性能上应该是一个量级的,不会有太大偏差
2. 两者有个区别就是 fastproto 支持自己的 message 里面引用其它人只用标准 proto 生成的 message ,比如 google 标准库里面的 Any 类型和 timestamp 类型。vtprotobuf 试了下不行。
3. Marshal 函数,gogoprotobuf 原来的实现是从后面往前写,fastproto 为了使用 protowire 这个库里面的标准函数,所以改成从前往后写。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/942950

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX