From f7d3a70d4c88ceda2fe090a60fae69cb9ef7ef64 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Fri, 31 Dec 2021 16:04:49 -0600 Subject: [PATCH] deflate_compress: use lazy2 compressor for levels 8-9 Instead of switching directly from the lazy compressor at level 7 to the near-optimal compressor at level 8, use the lazy2 compressor at levels 8-9 and don't switch to near-optimal until level 10. This avoids poor compression ratio and bad performance (both significantly worse than level 7, and significantly worse than zlib) at levels 8-9 on data where the near-optimal compressor doesn't do well until the parameters are cranked up. On data where the near-optimal compressor *does* do well, this change worsens the compression ratio of levels 8-9, but also speeds them up a lot, thus positioning them similarly vs. zlib as the lower levels (i.e. much faster and slightly stronger, rather than slightly faster and much stronger). The difference between levels 9 and 10 is increased, but that's perhaps the least bad place to have a discontinuity. Resolves https://github.com/ebiggers/libdeflate/issues/85 --- lib/deflate_compress.c | 42 +++++++++++++++++------------------------- 1 file changed, 17 insertions(+), 25 deletions(-) diff --git a/lib/deflate_compress.c b/lib/deflate_compress.c index 618d64c..c9308f0 100644 --- a/lib/deflate_compress.c +++ b/lib/deflate_compress.c @@ -33,9 +33,10 @@ /* * By default, the near-optimal parsing algorithm is enabled at compression - * level 8 and above. The near-optimal parsing algorithm produces a compression - * ratio significantly better than the greedy and lazy algorithms implemented - * here, and also the algorithm used by zlib at level 9. However, it is slow. + * level 10 and above. The near-optimal parsing algorithm produces a + * compression ratio significantly better than the greedy and lazy algorithms + * implemented here, and also the algorithm used by zlib at level 9. However, + * it is slow. */ #define SUPPORT_NEAR_OPTIMAL_PARSING 1 @@ -2789,7 +2790,7 @@ libdeflate_alloc_compressor(int compression_level) return NULL; #if SUPPORT_NEAR_OPTIMAL_PARSING - if (compression_level >= 8) + if (compression_level >= 10) size += sizeof(c->p.n); else if (compression_level >= 1) size += sizeof(c->p.g); @@ -2849,19 +2850,20 @@ libdeflate_alloc_compressor(int compression_level) c->max_search_depth = 100; c->nice_match_length = 130; break; -#if SUPPORT_NEAR_OPTIMAL_PARSING case 8: - c->impl = deflate_compress_near_optimal; - c->max_search_depth = 12; - c->nice_match_length = 20; - c->p.n.num_optim_passes = 1; + c->impl = deflate_compress_lazy2; + c->max_search_depth = 300; + c->nice_match_length = DEFLATE_MAX_MATCH_LEN; break; case 9: - c->impl = deflate_compress_near_optimal; - c->max_search_depth = 16; - c->nice_match_length = 26; - c->p.n.num_optim_passes = 2; +#if !SUPPORT_NEAR_OPTIMAL_PARSING + default: +#endif + c->impl = deflate_compress_lazy2; + c->max_search_depth = 600; + c->nice_match_length = DEFLATE_MAX_MATCH_LEN; break; +#if SUPPORT_NEAR_OPTIMAL_PARSING case 10: c->impl = deflate_compress_near_optimal; c->max_search_depth = 30; @@ -2874,24 +2876,14 @@ libdeflate_alloc_compressor(int compression_level) c->nice_match_length = 80; c->p.n.num_optim_passes = 3; break; + case 12: default: c->impl = deflate_compress_near_optimal; c->max_search_depth = 100; c->nice_match_length = 133; c->p.n.num_optim_passes = 4; break; -#else - case 8: - c->impl = deflate_compress_lazy; - c->max_search_depth = 150; - c->nice_match_length = 200; - break; - default: - c->impl = deflate_compress_lazy; - c->max_search_depth = 200; - c->nice_match_length = DEFLATE_MAX_MATCH_LEN; - break; -#endif +#endif /* SUPPORT_NEAR_OPTIMAL_PARSING */ } deflate_init_offset_slot_fast(c);