deflate_compress: introduce the lazy2 compressor

Add deflate_compress_lazy2(), which is a slightly stronger variant of
deflate_compress_lazy().  It looks ahead 2 positions instead of 1.
This commit is contained in:
Eric Biggers 2021-12-31 16:04:49 -06:00
parent f699b697d6
commit 1b3eaf2f13

View File

@ -2070,15 +2070,11 @@ deflate_compress_greedy(struct libdeflate_compressor * restrict c,
return deflate_flush_output(&os);
}
/*
* This is the "lazy" DEFLATE compressor. Before choosing a match, it checks to
* see if there's a better match at the next position. If yes, it outputs a
* literal and continues to the next position. If no, it outputs the match.
*/
static size_t
deflate_compress_lazy(struct libdeflate_compressor * restrict c,
const u8 * restrict in, size_t in_nbytes,
u8 * restrict out, size_t out_nbytes_avail)
static forceinline size_t
deflate_compress_lazy_generic(struct libdeflate_compressor * restrict c,
const u8 * restrict in, size_t in_nbytes,
u8 * restrict out, size_t out_nbytes_avail,
bool lazy2)
{
const u8 *in_next = in;
const u8 *in_end = in_next + in_nbytes;
@ -2195,19 +2191,66 @@ deflate_compress_lazy(struct libdeflate_compressor * restrict c,
cur_offset = next_offset;
goto have_cur_match;
}
/*
* No better match at the next position. Output the
* current match.
*/
deflate_choose_match(c, cur_len, cur_offset,
&litrunlen, &next_seq);
in_next = hc_matchfinder_skip_positions(
if (lazy2) {
/* In lazy2 mode, look ahead another position */
adjust_max_and_nice_len(&max_len, &nice_len,
in_end - in_next);
next_len = hc_matchfinder_longest_match(
&c->p.g.hc_mf,
&in_cur_base,
in_next,
in_end,
cur_len - 2,
next_hashes);
in_next++,
cur_len - 1,
max_len,
nice_len,
c->max_search_depth >> 2,
next_hashes,
&next_offset);
if (next_len >= cur_len &&
4 * (int)(next_len - cur_len) +
((int)bsr32(cur_offset) -
(int)bsr32(next_offset)) > 6) {
/*
* There's a much better match two
* positions ahead, so use two literals.
*/
deflate_choose_literal(
c, *(in_next - 3), &litrunlen);
deflate_choose_literal(
c, *(in_next - 2), &litrunlen);
cur_len = next_len;
cur_offset = next_offset;
goto have_cur_match;
}
/*
* No better match at either of the next 2
* positions. Output the current match.
*/
deflate_choose_match(c, cur_len, cur_offset,
&litrunlen, &next_seq);
if (cur_len > 3)
in_next = hc_matchfinder_skip_positions(
&c->p.g.hc_mf,
&in_cur_base,
in_next,
in_end,
cur_len - 3,
next_hashes);
} else { /* !lazy2 */
/*
* No better match at the next position. Output
* the current match.
*/
deflate_choose_match(c, cur_len, cur_offset,
&litrunlen, &next_seq);
in_next = hc_matchfinder_skip_positions(
&c->p.g.hc_mf,
&in_cur_base,
in_next,
in_end,
cur_len - 2,
next_hashes);
}
/* Check if it's time to output another block. */
} while (in_next < in_max_block_end &&
!should_end_block(&c->split_stats,
@ -2222,6 +2265,34 @@ deflate_compress_lazy(struct libdeflate_compressor * restrict c,
return deflate_flush_output(&os);
}
/*
* This is the "lazy" DEFLATE compressor. Before choosing a match, it checks to
* see if there's a better match at the next position. If yes, it outputs a
* literal and continues to the next position. If no, it outputs the match.
*/
static size_t
deflate_compress_lazy(struct libdeflate_compressor * restrict c,
const u8 * restrict in, size_t in_nbytes,
u8 * restrict out, size_t out_nbytes_avail)
{
return deflate_compress_lazy_generic(c, in, in_nbytes, out,
out_nbytes_avail, false);
}
/*
* The lazy2 compressor. This is similar to the regular lazy one, but it looks
* for a better match at the next 2 positions rather than the next 1. This
* makes it take slightly more time, but compress some inputs slightly more.
*/
static size_t
deflate_compress_lazy2(struct libdeflate_compressor * restrict c,
const u8 * restrict in, size_t in_nbytes,
u8 * restrict out, size_t out_nbytes_avail)
{
return deflate_compress_lazy_generic(c, in, in_nbytes, out,
out_nbytes_avail, true);
}
#if SUPPORT_NEAR_OPTIMAL_PARSING
/*