mirror of
https://codeberg.org/icewind/bitbuffer.git
synced 2026-06-03 16:44:06 +02:00
cleanup
This commit is contained in:
parent
01a8edd782
commit
c28c83d5f4
2 changed files with 62 additions and 40 deletions
|
|
@ -43,7 +43,7 @@ fn perf_be(b: &mut Bencher) {
|
|||
}
|
||||
|
||||
#[bench]
|
||||
fn perf_f32(b: &mut Bencher) {
|
||||
fn perf_f32_be(b: &mut Bencher) {
|
||||
let data = vec![1u8; 1024 * 1024 * 10];
|
||||
let buffer = BitBuffer::new(data, BigEndian);
|
||||
b.iter(|| {
|
||||
|
|
@ -63,6 +63,27 @@ fn perf_f32(b: &mut Bencher) {
|
|||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn perf_f32_le(b: &mut Bencher) {
|
||||
let data = vec![1u8; 1024 * 1024 * 10];
|
||||
let buffer = BitBuffer::new(data, LittleEndian);
|
||||
b.iter(|| {
|
||||
let mut pos = 0;
|
||||
let len = buffer.bit_len();
|
||||
let mut result: f32 = 0.0;
|
||||
loop {
|
||||
if pos + 32 > len {
|
||||
break;
|
||||
}
|
||||
let num = buffer.read_float::<f32>(pos).unwrap();
|
||||
result += num;
|
||||
pos += 32;
|
||||
}
|
||||
assert_eq!(result, 0.00000000000000000000000000000006170106);
|
||||
test::black_box(result);
|
||||
});
|
||||
}
|
||||
|
||||
const F64_RESULT: f64 = 0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010156250477904244;
|
||||
|
||||
#[bench]
|
||||
|
|
|
|||
|
|
@ -86,38 +86,43 @@ where
|
|||
}
|
||||
|
||||
fn read_usize_bytes(&self, byte_index: usize) -> [u8; USIZE_SIZE] {
|
||||
if byte_index + USIZE_SIZE <= self.bytes.len() {
|
||||
self.bytes[byte_index..byte_index + USIZE_SIZE]
|
||||
.try_into()
|
||||
.unwrap()
|
||||
if cfg!(feature = "unsafe") {
|
||||
use std::mem::transmute;
|
||||
// panic instead of accessing out of bounds data when the caller didn't do it's job bounds checking
|
||||
// due to the magic of branch prediction and this check "always" passing, the cost for this
|
||||
// is below the point of being measurable by `cargo bench`
|
||||
unsafe {
|
||||
let ptr = self.bytes.as_ptr().add(byte_index);
|
||||
*transmute::<_, &[u8; USIZE_SIZE]>(ptr)
|
||||
}
|
||||
} else {
|
||||
let mut bytes = [0; USIZE_SIZE];
|
||||
let copy_bytes = self.bytes.len() - byte_index;
|
||||
bytes[0..copy_bytes].copy_from_slice(&self.bytes[byte_index..byte_index + copy_bytes]);
|
||||
bytes
|
||||
if byte_index + USIZE_SIZE <= self.bytes.len() {
|
||||
self.bytes[byte_index..byte_index + USIZE_SIZE]
|
||||
.try_into()
|
||||
.unwrap()
|
||||
} else {
|
||||
let mut bytes = [0; USIZE_SIZE];
|
||||
let copy_bytes = self.bytes.len() - byte_index;
|
||||
bytes[0..copy_bytes]
|
||||
.copy_from_slice(&self.bytes[byte_index..byte_index + copy_bytes]);
|
||||
bytes
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// note that only the bottom USIZE - 1 bytes are usable
|
||||
fn read_shifted_usize(&self, byte_index: usize, shift: usize) -> usize {
|
||||
let raw_bytes: [u8; USIZE_SIZE] = self.read_usize_bytes(byte_index);
|
||||
let raw_usize: usize = usize::from_le_bytes(raw_bytes);
|
||||
raw_usize >> shift
|
||||
}
|
||||
|
||||
fn read_usize(&self, position: usize, count: usize) -> usize {
|
||||
let byte_index = position / 8;
|
||||
let bit_offset = position & 7;
|
||||
let usize_bit_size = size_of::<usize>() * 8;
|
||||
|
||||
let bytes: [u8; USIZE_SIZE] = if cfg!(feature = "unsafe") {
|
||||
use std::mem::transmute;
|
||||
// panic instead of accessing out of bounds data when the caller didn't do it's job bounds checking
|
||||
// due to the magic of branch prediction and this check "always" passing, the cost for this
|
||||
// is below the point of being measurable by `cargo bench`
|
||||
assert!(position + count <= self.bit_len());
|
||||
|
||||
unsafe {
|
||||
// this is safe here because we already have checks that we don't read past the slice
|
||||
let ptr = self.bytes.as_ptr().add(byte_index);
|
||||
*transmute::<_, &[u8; USIZE_SIZE]>(ptr)
|
||||
}
|
||||
} else {
|
||||
self.read_usize_bytes(byte_index)
|
||||
};
|
||||
let bytes: [u8; USIZE_SIZE] = self.read_usize_bytes(byte_index);
|
||||
|
||||
let container = if E::is_le() {
|
||||
usize::from_le_bytes(bytes)
|
||||
|
|
@ -359,21 +364,21 @@ where
|
|||
|
||||
let mut data = Vec::with_capacity(byte_count);
|
||||
let mut byte_left = byte_count;
|
||||
let max_read = size_of::<usize>() - 1;
|
||||
let mut read_pos = position / 8;
|
||||
while byte_left > 0 {
|
||||
let raw_bytes: [u8; USIZE_SIZE] = self.read_usize_bytes(read_pos);
|
||||
let raw_usize: usize = usize::from_le_bytes(raw_bytes);
|
||||
let shifted = raw_usize >> shift;
|
||||
|
||||
let bytes: [u8; USIZE_SIZE] = shifted.to_le_bytes();
|
||||
let read_bytes = min(byte_left, USIZE_SIZE - 1);
|
||||
while byte_left > USIZE_SIZE - 1 {
|
||||
let bytes = self.read_shifted_usize(read_pos, shift).to_le_bytes();
|
||||
let read_bytes = USIZE_SIZE - 1;
|
||||
let usable_bytes = &bytes[0..read_bytes];
|
||||
data.extend_from_slice(usable_bytes);
|
||||
|
||||
read_pos += read_bytes;
|
||||
byte_left -= read_bytes;
|
||||
}
|
||||
|
||||
let bytes = self.read_shifted_usize(read_pos, shift).to_le_bytes();
|
||||
let usable_bytes = &bytes[0..byte_left];
|
||||
data.extend_from_slice(usable_bytes);
|
||||
|
||||
Ok(data)
|
||||
}
|
||||
|
||||
|
|
@ -437,21 +442,17 @@ where
|
|||
#[inline]
|
||||
fn read_string_bytes(&self, position: usize) -> Result<Vec<u8>> {
|
||||
let shift = position & 7;
|
||||
if shift == 0 {
|
||||
if false && shift == 0 {
|
||||
let byte_index = position / 8;
|
||||
Ok(self.bytes[byte_index..self.find_null_byte(byte_index)].to_vec())
|
||||
} else {
|
||||
let mut acc = Vec::with_capacity(32);
|
||||
let mut pos = position;
|
||||
let mut byte_index = position / 8;
|
||||
loop {
|
||||
// note: if less then a usize worth of data is left in the buffer, read_usize_bytes
|
||||
// will automatically pad with null bytes, triggering the loop termination
|
||||
// thus no separate logic for dealing with the end of the bytes is required
|
||||
|
||||
let byte_index = pos / 8;
|
||||
let raw_bytes: [u8; USIZE_SIZE] = self.read_usize_bytes(byte_index);
|
||||
let raw_usize: usize = usize::from_le_bytes(raw_bytes);
|
||||
let shifted = raw_usize >> shift;
|
||||
let shifted = self.read_shifted_usize(byte_index, shift);
|
||||
|
||||
let has_null = contains_zero_byte_non_top(shifted);
|
||||
let bytes: [u8; USIZE_SIZE] = shifted.to_le_bytes();
|
||||
|
|
@ -468,7 +469,7 @@ where
|
|||
|
||||
acc.extend_from_slice(&usable_bytes[0..USIZE_SIZE - 1]);
|
||||
|
||||
pos += (USIZE_SIZE - 1) * 8;
|
||||
byte_index += USIZE_SIZE - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue