Optimize zippy decompression by making IncrementalCopy faster.

When SSSE3 is available:
- Use PSHUFB (_mm_shuffle_epi8) to handle pattern size 1 to 15 (previously it handled size 1 to 7).
- This enables us to do 16 byte copies instead of 8 bytes copies because we know that the pattern size >= 16.
- Use shuffle-reshuffle strategy to generate the next pattern after loading the initial pattern. This enables us to write 4 conditionals (similar to when pattern size >= 16) which would allow FDO to layout the code with respect to actual probabilities of each length.
- The PSHUFB masks are now generated programmatically at compile-time.

When SSSE3 is unavailable:
- No change.

In both cases:
- assert(op < op_limit) in IncrementalCopy so that we can check 'op_limit <= buf_limit - 15' instead of 'op_limit <= buf_limit - 16'. All existing call sites of IncrementalCopy guarantee this.

'bin' case is notably >20% faster because it has many repeated character patterns (i.e. pattern_size = 1).

PiperOrigin-RevId: 346454471
This commit is contained in:
Shahriar Rouf
2020-12-09 02:27:22 +00:00
committed by Victor Costan
parent 56c2c247d0
commit a9730ed505
2 changed files with 267 additions and 58 deletions

View File

@@ -695,6 +695,41 @@ TEST(Snappy, SimpleTests) {
Verify("abcaaaaaaa" + std::string(65536, 'b') + std::string("aaaaa") + "abc");
}
// Regression test for cr/345340892.
TEST(Snappy, AppendSelfPatternExtensionEdgeCases) {
Verify("abcabcabcabcabcabcab");
Verify("abcabcabcabcabcabcab0123456789ABCDEF");
Verify("abcabcabcabcabcabcabcabcabcabcabcabc");
Verify("abcabcabcabcabcabcabcabcabcabcabcabc0123456789ABCDEF");
}
// Regression test for cr/345340892.
TEST(Snappy, AppendSelfPatternExtensionEdgeCasesExhaustive) {
std::mt19937 rng;
std::uniform_int_distribution<int> uniform_byte(0, 255);
for (int pattern_size = 1; pattern_size <= 18; ++pattern_size) {
for (int length = 1; length <= 64; ++length) {
for (int extra_bytes_after_pattern : {0, 1, 15, 16, 128}) {
const int size = pattern_size + length + extra_bytes_after_pattern;
std::string input;
input.resize(size);
for (int i = 0; i < pattern_size; ++i) {
input[i] = 'a' + i;
}
for (int i = 0; i < length; ++i) {
input[pattern_size + i] = input[i];
}
for (int i = 0; i < extra_bytes_after_pattern; ++i) {
input[pattern_size + length + i] =
static_cast<char>(uniform_byte(rng));
}
Verify(input);
}
}
}
}
// Verify max blowup (lots of four-byte copies)
TEST(Snappy, MaxBlowup) {
std::mt19937 rng;
@@ -1285,6 +1320,12 @@ static struct {
{ "gaviota", "kppkn.gtb", 0 },
};
TEST(Snappy, TestBenchmarkFiles) {
for (int i = 0; i < ARRAYSIZE(files); ++i) {
Verify(ReadTestDataFile(files[i].filename, files[i].size_limit));
}
}
static void BM_UFlat(int iters, int arg) {
StopBenchmarkTiming();