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:
committed by
Victor Costan
parent
56c2c247d0
commit
a9730ed505
@@ -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();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user