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
This commit is contained in:
Eric Biggers 2021-12-31 16:04:49 -06:00
parent 1b3eaf2f13
commit f7d3a70d4c

View File

@ -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);