Skip to content

Commit 8a8c5dd

Browse files
committed
optimize varint encoded len calculation
Based on the cpp Protobuf implementation. This is a big win: encoded_len_varint is now constant time WRT the input integer size. name control ns/iter variable ns/iter diff ns/iter diff % speedup encoded_len_varint_small 111 (7207 MB/s) 110 (7272 MB/s) -1 -0.90% x 1.01 encoded_len_varint_medium 361 (2216 MB/s) 110 (7272 MB/s) -251 -69.53% x 3.28 encoded_len_varint_mixed 420 (1904 MB/s) 111 (7207 MB/s) -309 -73.57% x 3.78 encoded_len_varint_large 464 (1724 MB/s) 110 (7272 MB/s) -354 -76.29% x 4.22
1 parent 47d4c0f commit 8a8c5dd

1 file changed

Lines changed: 3 additions & 10 deletions

File tree

src/encoding.rs

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -140,16 +140,9 @@ fn decode_varint_slow<B>(buf: &mut B) -> Result<u64, DecodeError> where B: Buf {
140140
/// The returned value will be between 1 and 10, inclusive.
141141
#[inline]
142142
pub fn encoded_len_varint(value: u64) -> usize {
143-
if value < 1 << 7 { 1 }
144-
else if value < 1 << 14 { 2 }
145-
else if value < 1 << 21 { 3 }
146-
else if value < 1 << 28 { 4 }
147-
else if value < 1 << 35 { 5 }
148-
else if value < 1 << 42 { 6 }
149-
else if value < 1 << 49 { 7 }
150-
else if value < 1 << 56 { 8 }
151-
else if value < 1 << 63 { 9 }
152-
else { 10 }
143+
// Based on [VarintSize64][1].
144+
// [1]: https://github.com/google/protobuf/blob/3.3.x/src/google/protobuf/io/coded_stream.h#L1301-L1309
145+
((((value | 1).leading_zeros() ^ 63) * 9 + 73) / 64) as usize
153146
}
154147

155148
#[derive(Clone, Copy, Debug, PartialEq)]

0 commit comments

Comments
 (0)