Compare 4 bytes when checking if a longer match is possible.

Loading and comparing 4 bytes is ~as fast as 1 byte, but allows us to avoid more full match length calculation.

PiperOrigin-RevId: 617556847
This commit is contained in:
Brotli 2024-03-20 10:29:20 -07:00 committed by Copybara-Service
parent 9717649c31
commit 9351fa7ffb
5 changed files with 34 additions and 6 deletions

View File

@ -574,6 +574,11 @@ static BROTLI_INLINE void FindCompoundDictionaryMatch(
} }
} }
} }
/* we require matches of len >4, so increase best_len to 3, so we can compare
* 4 bytes all the time. */
if (best_len < 3) {
best_len = 3;
}
while (item == 0) { while (item == 0) {
size_t offset; size_t offset;
size_t distance; size_t distance;
@ -586,9 +591,10 @@ static BROTLI_INLINE void FindCompoundDictionaryMatch(
limit = source_size - offset; limit = source_size - offset;
limit = (limit > max_length) ? max_length : limit; limit = (limit > max_length) ? max_length : limit;
if (distance > max_distance) continue; if (distance > max_distance) continue;
if (cur_ix_masked + best_len > ring_buffer_mask || if (cur_ix_masked + best_len > ring_buffer_mask || best_len >= limit ||
best_len >= limit || /* compare 4 bytes ending at best_len + 1 */
data[cur_ix_masked + best_len] != source[offset + best_len]) { BrotliUnalignedRead32(&data[cur_ix_masked + best_len - 3]) !=
BrotliUnalignedRead32(&source[offset + best_len - 3])) {
continue; continue;
} }
{ {

View File

@ -241,6 +241,11 @@ static BROTLI_INLINE void FN(FindLongestMatch)(
} }
} }
} }
/* we require matches of len >4, so increase best_len to 3, so we can compare
* 4 bytes all the time. */
if (best_len < 3) {
best_len = 3;
}
{ {
const size_t bank = key & (NUM_BANKS - 1); const size_t bank = key & (NUM_BANKS - 1);
size_t backward = 0; size_t backward = 0;
@ -257,7 +262,9 @@ static BROTLI_INLINE void FN(FindLongestMatch)(
delta = banks[bank].slots[last].delta; delta = banks[bank].slots[last].delta;
if (cur_ix_masked + best_len > ring_buffer_mask || if (cur_ix_masked + best_len > ring_buffer_mask ||
prev_ix + best_len > ring_buffer_mask || prev_ix + best_len > ring_buffer_mask ||
data[cur_ix_masked + best_len] != data[prev_ix + best_len]) { /* compare 4 bytes ending at best_len + 1 */
BrotliUnalignedRead32(&data[cur_ix_masked + best_len - 3]) !=
BrotliUnalignedRead32(&data[prev_ix + best_len - 3])) {
continue; continue;
} }
{ {

View File

@ -211,6 +211,11 @@ static BROTLI_INLINE void FN(FindLongestMatch)(
} }
} }
} }
/* we require matches of len >4, so increase best_len to 3, so we can compare
* 4 bytes all the time. */
if (best_len < 3) {
best_len = 3;
}
{ {
const size_t key = FN(HashBytes)(&data[cur_ix_masked], self->hash_mul_); const size_t key = FN(HashBytes)(&data[cur_ix_masked], self->hash_mul_);
uint32_t* BROTLI_RESTRICT bucket = &buckets[key << self->block_bits_]; uint32_t* BROTLI_RESTRICT bucket = &buckets[key << self->block_bits_];
@ -230,7 +235,9 @@ static BROTLI_INLINE void FN(FindLongestMatch)(
prev_ix &= ring_buffer_mask; prev_ix &= ring_buffer_mask;
if (cur_ix_masked + best_len > ring_buffer_mask || if (cur_ix_masked + best_len > ring_buffer_mask ||
prev_ix + best_len > ring_buffer_mask || prev_ix + best_len > ring_buffer_mask ||
data[cur_ix_masked + best_len] != data[prev_ix + best_len]) { /* compare 4 bytes ending at best_len + 1 */
BrotliUnalignedRead32(&data[cur_ix_masked + best_len - 3]) !=
BrotliUnalignedRead32(&data[prev_ix + best_len - 3])) {
continue; continue;
} }
current4 = BrotliUnalignedRead32(data + prev_ix); current4 = BrotliUnalignedRead32(data + prev_ix);

View File

@ -208,6 +208,11 @@ static BROTLI_INLINE void FN(FindLongestMatch)(
} }
} }
} }
/* we require matches of len >4, so increase best_len to 3, so we can compare
* 4 bytes all the time. */
if (best_len < 3) {
best_len = 3;
}
{ {
const uint32_t key = const uint32_t key =
FN(HashBytes)(&data[cur_ix_masked], self->hash_shift_); FN(HashBytes)(&data[cur_ix_masked], self->hash_shift_);
@ -223,7 +228,9 @@ static BROTLI_INLINE void FN(FindLongestMatch)(
prev_ix &= ring_buffer_mask; prev_ix &= ring_buffer_mask;
if (cur_ix_masked + best_len > ring_buffer_mask || if (cur_ix_masked + best_len > ring_buffer_mask ||
prev_ix + best_len > ring_buffer_mask || prev_ix + best_len > ring_buffer_mask ||
data[cur_ix_masked + best_len] != data[prev_ix + best_len]) { /* compare 4 bytes ending at best_len + 1 */
BrotliUnalignedRead32(&data[cur_ix_masked + best_len - 3]) !=
BrotliUnalignedRead32(&data[prev_ix + best_len - 3])) {
continue; continue;
} }
{ {

View File

@ -155,6 +155,7 @@ static BROTLI_INLINE void FN(FindLongestMatch)(
uint32_t* BROTLI_RESTRICT buckets = self->buckets_; uint32_t* BROTLI_RESTRICT buckets = self->buckets_;
const size_t best_len_in = out->len; const size_t best_len_in = out->len;
const size_t cur_ix_masked = cur_ix & ring_buffer_mask; const size_t cur_ix_masked = cur_ix & ring_buffer_mask;
/* TODO: compare 4 bytes at once (and set the minimum best len to 4) */
int compare_char = data[cur_ix_masked + best_len_in]; int compare_char = data[cur_ix_masked + best_len_in];
size_t key = FN(HashBytes)(&data[cur_ix_masked]); size_t key = FN(HashBytes)(&data[cur_ix_masked]);
size_t key_out; size_t key_out;