From 6d9d77638172a50c1fa349f8f81ed5a951e4716b Mon Sep 17 00:00:00 2001 From: pommicket Date: Tue, 5 Sep 2023 19:28:37 -0400 Subject: small optimization --- README.md | 5 +++++ src/lib.rs | 20 ++++++++++++++++---- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index c697fbf..551251e 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,11 @@ A `pre-commit` git hook is provided to run `cargo fmt` and `cargo clippy`. You c ln -s ../../pre-commit .git/hooks/ ``` +## Performance + +Benchmarks (see `cargo bench`) show that `tiny-png` is about 50% slower than `png` +for large images, but faster than `png` for small images. + ## License > Zero-Clause BSD diff --git a/src/lib.rs b/src/lib.rs index 499bfb1..63ae94f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -52,6 +52,9 @@ pub enum Error { BadAdlerChecksum, } +#[cold] +fn cold() {} + /// alias for `Result` pub type Result = core::result::Result; @@ -344,8 +347,18 @@ impl<'a> From> for BitReader<'a> { impl BitReader<'_> { fn read_more_bits(&mut self) -> Result<()> { - let mut new_bits = [0; ReadBits::BITS as usize / 8]; - self.inner.read(&mut new_bits)?; + const BYTES: usize = ReadBits::BITS as usize / 8; + let mut new_bits = [0; BYTES]; + let block_reader = &mut self.inner.block_reader.0; + if block_reader.len() >= BYTES { + // no bull shit goin on we can go right past everyone + // (fast path for ~99.9% of calls) + new_bits.copy_from_slice(&block_reader[..BYTES]); + *block_reader = &block_reader[BYTES..]; + } else { + cold(); + self.inner.read(&mut new_bits)?; + } let new_bits = Bits::from(ReadBits::from_le_bytes(new_bits)); self.bits |= new_bits << self.bits_left; self.bits_left += ReadBits::BITS as u8; @@ -362,8 +375,7 @@ impl BitReader<'_> { fn read_bits(&mut self, count: u8) -> Result { let bits = self.peek_bits(count)?; - self.bits_left -= count; - self.bits >>= count; + self.skip_peeked_bits(count); Ok(bits) } -- cgit v1.2.3