在Protocol Buffers和Avro中ZigZag编码背后的原因是什么?

End*_*rju 12 performance protocol-buffers avro zigzag-encoding

ZigZag需要大量的开销才能写入/读取数字.实际上我惊呆了,看到它不仅仅是按原样写入int/long值,而是进行了大量额外的加扰.甚至还有一个循环:https: //github.com/mardambey/mypipe/blob/master/avro/lang/java/avro/src/main/java/org/apache/avro/io/DirectBinaryEncoder.java#L90

我似乎无法在Protocol Buffers文档或Avro文档中找到,或者说我自己,那些扰乱数字的优势是什么?为什么在编码后交替使用正数和负数会更好?

为什么他们不只是用little-endian,big-endian,网络顺序编写,只需要将它们读入内存并可能反转位字节序?我们用性能支付什么?

Han*_*ant 12

它是一个可变长度的7位编码.编码值的第一个字节将高位设置为0,后续字节将其设置为1.这是解码器可以判断使用了多少字节来编码值的方式.无论机器架构如何,字节顺序总是小端的.

这是一种编码技巧,允许根据需要编写少量字节来编码值.因此,长度为8字节,值介于-64和63之间的只需要一个字节.这很常见,long提供的范围在实践中很少使用.

在没有gzip式压缩方法的开销的情况下紧密打包数据是设计目标.也用于.NET Framework.进行/解码该值所需的处理器开销是无关紧要的.已经远低于压缩方案,它只占I/O成本的很小一部分.

  • 非常感谢。我真的很感谢你的帮助。现在它完全有道理了。我迷路了,因为我开始查看Java源代码,这些源代码[在某些地方进行了不必要的混淆](https://github.com/mardambey/mypipe/blob/master/avro/lang/java/avro/src /main/java/org/apache/avro/io/BinaryDecoder.java#L195)。天哪,Java 真的需要手工编写的循环展开代码才能快速运行吗? (2认同)
  • 有可能,但在针对嵌入式系统时可能不会。乐观地,人们希望有人实际测试过代码并验证它是否提供了好处。实际上,它可能被验证为正确且具有足够的性能,然后被忽略。除非他们已经因为其他原因而对其进行了修改,否则熟练的专业人员通常会犹豫是否要修改工作代码来满足性能和正确性目标。您也许能够分析更改历史记录以找出展开该循环的原因;也许这是为了响应基准而完成的? (2认同)
  • 这个答案的第二句话是错误的。每个八位字节的最高有效位被保留以指示编码是否继续。例外是第 9 个八位字节,其中所有 8 位都代表值的一部分。 (2认同)
  • 一个经常丢失的快速评论——通常传输/传输一个字节所需的时间大大超过了奇怪编码所需的处理时间。即使在 1Gb/s 线速下,运行在 2+ GHz 的现代处理器也将通过在简单编码而不是传输上花费周期来“获胜”。在某些环境(例如 IoT 和 BLE)中,带宽受到如此限制,而处理器的性能相对更高,因此奇怪的编码是一个巨大的胜利。 (2认同)