From 7315932413ad7b442cbfae6457dd3733b58403dc Mon Sep 17 00:00:00 2001 From: Chris Hennick Date: Sun, 2 Jul 2023 09:55:50 -0700 Subject: [PATCH 01/11] Use an object pool for ZopfliHash instances --- Cargo.lock | 7 +++++++ Cargo.toml | 1 + src/hash.rs | 4 ++++ src/lz77.rs | 5 +++-- src/squeeze.rs | 5 +++-- 5 files changed, 18 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 91ba54e..fbf4ce0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -159,6 +159,12 @@ version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" +[[package]] +name = "lockfree-object-pool" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee33defb27b106378a6efcfcde4dda6226dfdac8ba7a2904f5bc93363cb88557" + [[package]] name = "log" version = "0.4.19" @@ -525,6 +531,7 @@ name = "zopfli" version = "0.7.4" dependencies = [ "crc32fast", + "lockfree-object-pool", "log", "miniz_oxide", "proptest", diff --git a/Cargo.toml b/Cargo.toml index 55a18d9..097734d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,7 @@ crc32fast = { version = "1.3.2", default-features = false, optional = true } simd-adler32 = { version = "0.3.5", default-features = false, optional = true } typed-arena = { version = "2.0.2", default-features = false } log = "0.4.19" +lockfree-object-pool = "0.1.4" [dev-dependencies] proptest = "1.2.0" diff --git a/src/hash.rs b/src/hash.rs index c64aa3a..3f5f75b 100644 --- a/src/hash.rs +++ b/src/hash.rs @@ -1,4 +1,5 @@ use alloc::vec::Vec; +use lockfree_object_pool::LinearObjectPool; use crate::util::{ZOPFLI_MIN_MATCH, ZOPFLI_WINDOW_MASK, ZOPFLI_WINDOW_SIZE}; @@ -157,3 +158,6 @@ impl ZopfliHash { } } } + +pub const HASH_POOL: LinearObjectPool = LinearObjectPool::new( + ZopfliHash::new, ZopfliHash::reset); diff --git a/src/lz77.rs b/src/lz77.rs index ea992a1..77e6609 100644 --- a/src/lz77.rs +++ b/src/lz77.rs @@ -11,6 +11,7 @@ use crate::{ }, Options, }; +use crate::hash::HASH_POOL; #[derive(Clone, Copy)] pub enum LitLen { @@ -146,7 +147,7 @@ impl Lz77Store { return; } let windowstart = instart.saturating_sub(ZOPFLI_WINDOW_SIZE); - let mut h = ZopfliHash::new(); + let mut h = HASH_POOL.pull(); let arr = &in_data[..inend]; h.warmup(arr, windowstart, inend); @@ -246,7 +247,7 @@ impl Lz77Store { return; } - let mut h = ZopfliHash::new(); + let mut h = HASH_POOL.pull(); let arr = &in_data[..inend]; h.warmup(arr, windowstart, inend); diff --git a/src/squeeze.rs b/src/squeeze.rs index 10ac6af..04b032f 100644 --- a/src/squeeze.rs +++ b/src/squeeze.rs @@ -20,6 +20,7 @@ use crate::{ symbols::{get_dist_extra_bits, get_dist_symbol, get_length_extra_bits, get_length_symbol}, util::{ZOPFLI_MAX_MATCH, ZOPFLI_NUM_D, ZOPFLI_NUM_LL, ZOPFLI_WINDOW_MASK, ZOPFLI_WINDOW_SIZE}, }; +use crate::hash::HASH_POOL; const K_INV_LOG2: f64 = core::f64::consts::LOG2_E; // 1.0 / log(2.0) @@ -422,7 +423,7 @@ pub fn lz77_optimal_fixed( ) { s.blockstart = instart; s.blockend = inend; - let mut h = ZopfliHash::new(); + let mut h = HASH_POOL.pull(); let mut costs = Vec::with_capacity(inend - instart); lz77_optimal_run( s, @@ -456,7 +457,7 @@ pub fn lz77_optimal( let mut stats = SymbolStats::default(); stats.get_statistics(¤tstore); - let mut h = ZopfliHash::new(); + let mut h = HASH_POOL.pull(); let mut costs = Vec::with_capacity(inend - instart + 1); let mut beststats = SymbolStats::default(); From 8c463b8a3fb386ec0a903f582e1c762756ed1768 Mon Sep 17 00:00:00 2001 From: Chris Hennick Date: Sun, 2 Jul 2023 10:08:56 -0700 Subject: [PATCH 02/11] Bug fix: need let-bindings to prevent E0716 --- src/lz77.rs | 6 ++++-- src/squeeze.rs | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/lz77.rs b/src/lz77.rs index 77e6609..c170fd4 100644 --- a/src/lz77.rs +++ b/src/lz77.rs @@ -147,7 +147,8 @@ impl Lz77Store { return; } let windowstart = instart.saturating_sub(ZOPFLI_WINDOW_SIZE); - let mut h = HASH_POOL.pull(); + let hash_pool = &*HASH_POOL; + let mut h = hash_pool.pull(); let arr = &in_data[..inend]; h.warmup(arr, windowstart, inend); @@ -247,7 +248,8 @@ impl Lz77Store { return; } - let mut h = HASH_POOL.pull(); + let hash_pool = &*HASH_POOL; + let mut h = hash_pool.pull(); let arr = &in_data[..inend]; h.warmup(arr, windowstart, inend); diff --git a/src/squeeze.rs b/src/squeeze.rs index 04b032f..e4b1e81 100644 --- a/src/squeeze.rs +++ b/src/squeeze.rs @@ -423,7 +423,8 @@ pub fn lz77_optimal_fixed( ) { s.blockstart = instart; s.blockend = inend; - let mut h = HASH_POOL.pull(); + let hash_pool = &*HASH_POOL; + let mut h = hash_pool.pull(); let mut costs = Vec::with_capacity(inend - instart); lz77_optimal_run( s, @@ -457,7 +458,8 @@ pub fn lz77_optimal( let mut stats = SymbolStats::default(); stats.get_statistics(¤tstore); - let mut h = HASH_POOL.pull(); + let hash_pool = &*HASH_POOL; + let mut h = hash_pool.pull(); let mut costs = Vec::with_capacity(inend - instart + 1); let mut beststats = SymbolStats::default(); From c9fc8f4164a4c7defcbd346c5b733fe3520e3b25 Mon Sep 17 00:00:00 2001 From: Chris Hennick Date: Sun, 2 Jul 2023 10:10:16 -0700 Subject: [PATCH 03/11] Bug fix --- src/lz77.rs | 4 ++-- src/squeeze.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lz77.rs b/src/lz77.rs index c170fd4..ddb5ca0 100644 --- a/src/lz77.rs +++ b/src/lz77.rs @@ -147,7 +147,7 @@ impl Lz77Store { return; } let windowstart = instart.saturating_sub(ZOPFLI_WINDOW_SIZE); - let hash_pool = &*HASH_POOL; + let hash_pool = &HASH_POOL; let mut h = hash_pool.pull(); let arr = &in_data[..inend]; @@ -248,7 +248,7 @@ impl Lz77Store { return; } - let hash_pool = &*HASH_POOL; + let hash_pool = &HASH_POOL; let mut h = hash_pool.pull(); let arr = &in_data[..inend]; diff --git a/src/squeeze.rs b/src/squeeze.rs index e4b1e81..5981db4 100644 --- a/src/squeeze.rs +++ b/src/squeeze.rs @@ -423,7 +423,7 @@ pub fn lz77_optimal_fixed( ) { s.blockstart = instart; s.blockend = inend; - let hash_pool = &*HASH_POOL; + let hash_pool = &HASH_POOL; let mut h = hash_pool.pull(); let mut costs = Vec::with_capacity(inend - instart); lz77_optimal_run( @@ -458,7 +458,7 @@ pub fn lz77_optimal( let mut stats = SymbolStats::default(); stats.get_statistics(¤tstore); - let hash_pool = &*HASH_POOL; + let hash_pool = &HASH_POOL; let mut h = hash_pool.pull(); let mut costs = Vec::with_capacity(inend - instart + 1); From 84baacff5565f05e866cf888982808a2ff8e4d47 Mon Sep 17 00:00:00 2001 From: Chris Hennick Date: Sun, 2 Jul 2023 10:14:03 -0700 Subject: [PATCH 04/11] Bug fix: wrap HASH_POOL in a Lazy since it's not constant --- Cargo.lock | 7 +++++++ Cargo.toml | 1 + src/hash.rs | 5 +++-- src/lz77.rs | 4 ++-- src/squeeze.rs | 4 ++-- 5 files changed, 15 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fbf4ce0..ede4440 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -190,6 +190,12 @@ dependencies = [ "libm", ] +[[package]] +name = "once_cell" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -534,6 +540,7 @@ dependencies = [ "lockfree-object-pool", "log", "miniz_oxide", + "once_cell", "proptest", "proptest-derive", "simd-adler32", diff --git a/Cargo.toml b/Cargo.toml index 097734d..7194119 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,7 @@ simd-adler32 = { version = "0.3.5", default-features = false, optional = true } typed-arena = { version = "2.0.2", default-features = false } log = "0.4.19" lockfree-object-pool = "0.1.4" +once_cell = "1.18.0" [dev-dependencies] proptest = "1.2.0" diff --git a/src/hash.rs b/src/hash.rs index 3f5f75b..2135994 100644 --- a/src/hash.rs +++ b/src/hash.rs @@ -1,5 +1,6 @@ use alloc::vec::Vec; use lockfree_object_pool::LinearObjectPool; +use once_cell::sync::Lazy; use crate::util::{ZOPFLI_MIN_MATCH, ZOPFLI_WINDOW_MASK, ZOPFLI_WINDOW_SIZE}; @@ -159,5 +160,5 @@ impl ZopfliHash { } } -pub const HASH_POOL: LinearObjectPool = LinearObjectPool::new( - ZopfliHash::new, ZopfliHash::reset); +pub static HASH_POOL: Lazy> = Lazy::new(|| LinearObjectPool::new( + ZopfliHash::new, |hash| hash.reset())); diff --git a/src/lz77.rs b/src/lz77.rs index ddb5ca0..c170fd4 100644 --- a/src/lz77.rs +++ b/src/lz77.rs @@ -147,7 +147,7 @@ impl Lz77Store { return; } let windowstart = instart.saturating_sub(ZOPFLI_WINDOW_SIZE); - let hash_pool = &HASH_POOL; + let hash_pool = &*HASH_POOL; let mut h = hash_pool.pull(); let arr = &in_data[..inend]; @@ -248,7 +248,7 @@ impl Lz77Store { return; } - let hash_pool = &HASH_POOL; + let hash_pool = &*HASH_POOL; let mut h = hash_pool.pull(); let arr = &in_data[..inend]; diff --git a/src/squeeze.rs b/src/squeeze.rs index 5981db4..e4b1e81 100644 --- a/src/squeeze.rs +++ b/src/squeeze.rs @@ -423,7 +423,7 @@ pub fn lz77_optimal_fixed( ) { s.blockstart = instart; s.blockend = inend; - let hash_pool = &HASH_POOL; + let hash_pool = &*HASH_POOL; let mut h = hash_pool.pull(); let mut costs = Vec::with_capacity(inend - instart); lz77_optimal_run( @@ -458,7 +458,7 @@ pub fn lz77_optimal( let mut stats = SymbolStats::default(); stats.get_statistics(¤tstore); - let hash_pool = &HASH_POOL; + let hash_pool = &*HASH_POOL; let mut h = hash_pool.pull(); let mut costs = Vec::with_capacity(inend - instart + 1); From af4e4e43b9afac98c493c20be09fadb0309a236b Mon Sep 17 00:00:00 2001 From: Chris Hennick Date: Sun, 2 Jul 2023 10:18:46 -0700 Subject: [PATCH 05/11] cargo fmt --- src/hash.rs | 5 +++-- src/lz77.rs | 3 +-- src/squeeze.rs | 3 +-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/hash.rs b/src/hash.rs index 2135994..b62973f 100644 --- a/src/hash.rs +++ b/src/hash.rs @@ -1,4 +1,5 @@ use alloc::vec::Vec; + use lockfree_object_pool::LinearObjectPool; use once_cell::sync::Lazy; @@ -160,5 +161,5 @@ impl ZopfliHash { } } -pub static HASH_POOL: Lazy> = Lazy::new(|| LinearObjectPool::new( - ZopfliHash::new, |hash| hash.reset())); +pub static HASH_POOL: Lazy> = + Lazy::new(|| LinearObjectPool::new(ZopfliHash::new, ZopfliHash::reset)); diff --git a/src/lz77.rs b/src/lz77.rs index c170fd4..ddd4436 100644 --- a/src/lz77.rs +++ b/src/lz77.rs @@ -3,7 +3,7 @@ use core::cmp; use crate::{ cache::{Cache, NoCache, ZopfliLongestMatchCache}, - hash::{Which, ZopfliHash}, + hash::{Which, ZopfliHash, HASH_POOL}, symbols::{get_dist_symbol, get_length_symbol}, util::{ ZOPFLI_MAX_CHAIN_HITS, ZOPFLI_MAX_MATCH, ZOPFLI_MIN_MATCH, ZOPFLI_NUM_D, ZOPFLI_NUM_LL, @@ -11,7 +11,6 @@ use crate::{ }, Options, }; -use crate::hash::HASH_POOL; #[derive(Clone, Copy)] pub enum LitLen { diff --git a/src/squeeze.rs b/src/squeeze.rs index e4b1e81..4376ff2 100644 --- a/src/squeeze.rs +++ b/src/squeeze.rs @@ -15,12 +15,11 @@ use log::{debug, trace}; use crate::{ cache::Cache, deflate::{calculate_block_size, BlockType}, - hash::ZopfliHash, + hash::{ZopfliHash, HASH_POOL}, lz77::{find_longest_match, LitLen, Lz77Store, ZopfliBlockState}, symbols::{get_dist_extra_bits, get_dist_symbol, get_length_extra_bits, get_length_symbol}, util::{ZOPFLI_MAX_MATCH, ZOPFLI_NUM_D, ZOPFLI_NUM_LL, ZOPFLI_WINDOW_MASK, ZOPFLI_WINDOW_SIZE}, }; -use crate::hash::HASH_POOL; const K_INV_LOG2: f64 = core::f64::consts::LOG2_E; // 1.0 / log(2.0) From 50cd38ec6a3cc7dad87d0384ff34f821045a937b Mon Sep 17 00:00:00 2001 From: Chris Hennick Date: Sun, 2 Jul 2023 11:03:02 -0700 Subject: [PATCH 06/11] Add a method to prewarm HASH_POOL --- src/lib.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index baa7c1a..63b2931 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -66,6 +66,7 @@ use std::io::{Error, Write}; #[cfg(any(doc, not(feature = "std")))] pub use io::{Error, ErrorKind, Write}; +use crate::hash::HASH_POOL; /// Options for the Zopfli compression algorithm. #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -150,6 +151,12 @@ pub fn compress( } } +/// Populates object pools for expensive objects that Zopfli uses. Call this on a background thread +/// when you know ahead of time that compression will be needed. +pub fn prewarm_object_pools() { + HASH_POOL.pull(); +} + #[cfg(all(test, feature = "std"))] mod test { use std::io; From 386e74efd28329c1e6453a724f8bb154b4ff4728 Mon Sep 17 00:00:00 2001 From: Chris Hennick Date: Sun, 2 Jul 2023 11:11:23 -0700 Subject: [PATCH 07/11] cargo fmt --- src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib.rs b/src/lib.rs index 63b2931..08a76a4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -66,6 +66,7 @@ use std::io::{Error, Write}; #[cfg(any(doc, not(feature = "std")))] pub use io::{Error, ErrorKind, Write}; + use crate::hash::HASH_POOL; /// Options for the Zopfli compression algorithm. From 1c19c9e956b8e1dcb3ac0435d8cb374ac4e71195 Mon Sep 17 00:00:00 2001 From: Chris Hennick Date: Sat, 16 Mar 2024 20:10:43 -0700 Subject: [PATCH 08/11] Fix issues following rebase --- src/hash.rs | 4 ++-- src/lz77.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/hash.rs b/src/hash.rs index 2cee933..6cc13f3 100644 --- a/src/hash.rs +++ b/src/hash.rs @@ -180,5 +180,5 @@ impl ZopfliHash { } } -pub static HASH_POOL: Lazy> = - Lazy::new(|| LinearObjectPool::new(ZopfliHash::new, ZopfliHash::reset)); +pub static HASH_POOL: Lazy>> = + Lazy::new(|| LinearObjectPool::new(ZopfliHash::new, |boxed| boxed.reset())); diff --git a/src/lz77.rs b/src/lz77.rs index 2fab283..f3749e1 100644 --- a/src/lz77.rs +++ b/src/lz77.rs @@ -2,7 +2,7 @@ use alloc::{boxed::Box, vec::Vec}; use core::cmp; use crate::{ - cache::{Cache, NoCache, ZopfliLongestMatchCache}, + cache::{Cache}, hash::{Which, ZopfliHash, HASH_POOL}, symbols::{get_dist_symbol, get_length_symbol}, util::{ From b467faeee506eec72839a4c22d90f1ab6d2150bd Mon Sep 17 00:00:00 2001 From: Chris Hennick Date: Sat, 16 Mar 2024 20:11:58 -0700 Subject: [PATCH 09/11] cargo fmt --- src/lz77.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lz77.rs b/src/lz77.rs index f3749e1..470c913 100644 --- a/src/lz77.rs +++ b/src/lz77.rs @@ -2,7 +2,7 @@ use alloc::{boxed::Box, vec::Vec}; use core::cmp; use crate::{ - cache::{Cache}, + cache::Cache, hash::{Which, ZopfliHash, HASH_POOL}, symbols::{get_dist_symbol, get_length_symbol}, util::{ From bfe689c21749a85d195f0f48e18450dca31eceb6 Mon Sep 17 00:00:00 2001 From: Chris Hennick Date: Sat, 16 Mar 2024 21:14:11 -0700 Subject: [PATCH 10/11] Update new dependencies --- Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 3a5e42a..1faf3f5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,8 +24,8 @@ crc32fast = { version = "1.4.0", default-features = false, optional = true } simd-adler32 = { version = "0.3.7", default-features = false, optional = true } typed-arena = { version = "2.0.2", default-features = false } log = "0.4.21" -lockfree-object-pool = "0.1.4" -once_cell = "1.18.0" +lockfree-object-pool = "0.1.5" +once_cell = "1.19.0" [dev-dependencies] proptest = "1.4.0" From 6645bdc065c1749d12a45f31f5e73ffebc90eb78 Mon Sep 17 00:00:00 2001 From: Chris Hennick Date: Sat, 16 Mar 2024 21:14:48 -0700 Subject: [PATCH 11/11] Update new dependencies --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4cf2ba5..3124d5c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -161,9 +161,9 @@ checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" [[package]] name = "lockfree-object-pool" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee33defb27b106378a6efcfcde4dda6226dfdac8ba7a2904f5bc93363cb88557" +checksum = "3a69c0481fc2424cb55795de7da41add33372ea75a94f9b6588ab6a2826dfebc" [[package]] name = "log" @@ -192,9 +192,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "ppv-lite86"