Skip to content

Commit 5ae30c5

Browse files
authored
perf: NonZeroU64 to optimize encoded_len_varint (#1192)
The leading zeros count may perform better on many architectures when the zero case is excluded. Also use ilog2 as shorthand for the leading zeros trick because it makes more clearly what we mean to get, and should be ideally optimized by the compiler.
1 parent de2a009 commit 5ae30c5

File tree

1 file changed

+5
-2
lines changed

1 file changed

+5
-2
lines changed

prost/src/encoding/varint.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use core::cmp::min;
2+
use core::num::NonZeroU64;
23

34
use ::bytes::{Buf, BufMut};
45

@@ -25,8 +26,10 @@ pub fn encode_varint(mut value: u64, buf: &mut impl BufMut) {
2526
#[inline]
2627
pub fn encoded_len_varint(value: u64) -> usize {
2728
// Based on [VarintSize64][1].
28-
// [1]: https://github.com/google/protobuf/blob/3.3.x/src/google/protobuf/io/coded_stream.h#L1301-L1309
29-
((((value | 1).leading_zeros() ^ 63) * 9 + 73) / 64) as usize
29+
// [1]: https://github.com/protocolbuffers/protobuf/blob/v28.3/src/google/protobuf/io/coded_stream.h#L1744-L1756
30+
// Safety: value | 1 is non-zero.
31+
let log2value = unsafe { NonZeroU64::new_unchecked(value | 1) }.ilog2();
32+
((log2value * 9 + (64 + 9)) / 64) as usize
3033
}
3134

3235
/// Decodes a LEB128-encoded variable length integer from the buffer.

0 commit comments

Comments
 (0)