From ec744f59f94425b09f058c335588bb36183f8757 Mon Sep 17 00:00:00 2001 From: Mikhail Zabaluev Date: Sat, 23 Nov 2024 20:26:08 +0200 Subject: [PATCH] perf: NonZeroU64 to optimize encoded_len_varint 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. --- prost/src/encoding/varint.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/prost/src/encoding/varint.rs b/prost/src/encoding/varint.rs index 5c1b477aa..b913fe684 100644 --- a/prost/src/encoding/varint.rs +++ b/prost/src/encoding/varint.rs @@ -1,4 +1,5 @@ use core::cmp::min; +use core::num::NonZeroU64; use ::bytes::{Buf, BufMut}; @@ -25,8 +26,10 @@ pub fn encode_varint(mut value: u64, buf: &mut impl BufMut) { #[inline] pub fn encoded_len_varint(value: u64) -> usize { // Based on [VarintSize64][1]. - // [1]: https://github.com/google/protobuf/blob/3.3.x/src/google/protobuf/io/coded_stream.h#L1301-L1309 - ((((value | 1).leading_zeros() ^ 63) * 9 + 73) / 64) as usize + // [1]: https://github.com/protocolbuffers/protobuf/blob/v28.3/src/google/protobuf/io/coded_stream.h#L1744-L1756 + // Safety: value | 1 is non-zero. + let log2value = unsafe { NonZeroU64::new_unchecked(value | 1) }.ilog2(); + ((log2value * 9 + (64 + 9)) / 64) as usize } /// Decodes a LEB128-encoded variable length integer from the buffer.