Skip to content

Commit

Permalink
Branchless buffer refills for vector decoding
Browse files Browse the repository at this point in the history
This reduces the number instructions emitted by nearly half when we
check if there is enough data to blindly refill the lookahead. The best
part, we don't even need to use the unchecked API to blindly refill --
somehow the compiler can figured this out when we ensure there is at
least 16 bytes left unbuffered. Crazy.
  • Loading branch information
nickbabcock committed Dec 19, 2024
1 parent dbaa174 commit a938ffc
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 1 deletion.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ serde = { version = "1", features = ["derive"] }
encoding_rs = "0.8"
phf = { version = "0.11", features = ["macros"] }
fnv = "1.0"
bitter = "0.7"
bitter = "0.7.1"

[dev-dependencies]
serde_json = "1"
Expand Down
26 changes: 26 additions & 0 deletions src/network/models.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,32 @@ pub struct Vector3i {

impl Vector3i {
pub fn decode(bits: &mut LittleEndianReader<'_>, net_version: i32) -> Option<Vector3i> {
// Do we have enough data available to blindly refill the lookahead twice?
// Note: this code doesn't actually use the unchecked bitter API as the
// compiler was able to emit the same code with both as long as we
// ensured there was 16 bytes left (even though a `Vector3i` will never
// need that many bytes).
if bits.unbuffered_bytes_remaining() >= 16 {
bits.refill_lookahead();
let size_bits = bits.peek_bits_max_computed(4, if net_version >= 7 { 22 } else { 20 });
let bias = 1 << (size_bits + 1);
let bit_limit = (size_bits + 2) as u32;
let dx = bits.peek_and_consume(bit_limit) as u32;
bits.refill_lookahead();
let dy = bits.peek_and_consume(bit_limit) as u32;
let dz = bits.peek_and_consume(bit_limit) as u32;
Some(Vector3i {
x: (dx as i32) - bias,
y: (dy as i32) - bias,
z: (dz as i32) - bias,
})
} else {
Vector3i::eof_decode(bits, net_version)
}
}

#[cold]
pub fn eof_decode(bits: &mut LittleEndianReader<'_>, net_version: i32) -> Option<Vector3i> {
bits.refill_lookahead();
if bits.lookahead_bits() < 5 {
return None;
Expand Down

0 comments on commit a938ffc

Please sign in to comment.