Granule file performance benchmark and improvements (#7742)

* added cpu microbenchmark for blob granule files

* Added edge case read benchmarks, and sorting memory deltas

* Sorted merge for granule files

* key block comparison optimization in granule files

* More performance improvements to granule file read

* fixing zlib not supported build

* fixing formatting

* Added debug macro for new debugging prints

* review comments

* more strict compression size validation assert
This commit is contained in:
Josh Slocum 2022-08-02 11:36:44 -05:00 committed by GitHub
parent b1ff8b8340
commit 4b66645d80
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 1087 additions and 189 deletions

File diff suppressed because it is too large Load Diff

View File

@ -914,7 +914,7 @@ void ServerKnobs::initialize(Randomize randomize, ClientKnobs* clientKnobs, IsSi
init( BG_SNAPSHOT_FILE_TARGET_CHUNK_BYTES, 64*1024 ); if ( randomize && BUGGIFY ) BG_SNAPSHOT_FILE_TARGET_CHUNK_BYTES = BG_SNAPSHOT_FILE_TARGET_BYTES / (1 << deterministicRandom()->randomInt(0, 8));
init( BG_DELTA_BYTES_BEFORE_COMPACT, BG_SNAPSHOT_FILE_TARGET_BYTES/2 );
init( BG_DELTA_FILE_TARGET_BYTES, BG_DELTA_BYTES_BEFORE_COMPACT/10 );
init( BG_DELTA_FILE_TARGET_CHUNK_BYTES, 64*1024 ); if ( randomize && BUGGIFY ) BG_DELTA_FILE_TARGET_CHUNK_BYTES = BG_DELTA_FILE_TARGET_BYTES / (1 << deterministicRandom()->randomInt(0, 7));
init( BG_DELTA_FILE_TARGET_CHUNK_BYTES, 32*1024 ); if ( randomize && BUGGIFY ) BG_DELTA_FILE_TARGET_CHUNK_BYTES = BG_DELTA_FILE_TARGET_BYTES / (1 << deterministicRandom()->randomInt(0, 7));
init( BG_MAX_SPLIT_FANOUT, 10 ); if( randomize && BUGGIFY ) BG_MAX_SPLIT_FANOUT = deterministicRandom()->randomInt(5, 15);
init( BG_MAX_MERGE_FANIN, 10 ); if( randomize && BUGGIFY ) BG_MAX_MERGE_FANIN = deterministicRandom()->randomInt(2, 15);
init( BG_HOT_SNAPSHOT_VERSIONS, 5000000 );

View File

@ -27,13 +27,13 @@
#include "flow/CompressionUtils.h"
Value serializeChunkedSnapshot(const Standalone<StringRef>& fileNameRef,
Standalone<GranuleSnapshot> snapshot,
const Standalone<GranuleSnapshot>& snapshot,
int chunkSize,
Optional<CompressionFilter> compressFilter,
Optional<BlobGranuleCipherKeysCtx> cipherKeysCtx = {});
Value serializeChunkedDeltaFile(const Standalone<StringRef>& fileNameRef,
Standalone<GranuleDeltas> deltas,
const Standalone<GranuleDeltas>& deltas,
const KeyRangeRef& fileRange,
int chunkSize,
Optional<CompressionFilter> compressFilter,

View File

@ -34,40 +34,6 @@
#define deltatree_printf(...)
#endif
typedef uint64_t Word;
// Get the number of prefix bytes that are the same between a and b, up to their common length of cl
static inline int commonPrefixLength(uint8_t const* ap, uint8_t const* bp, int cl) {
int i = 0;
const int wordEnd = cl - sizeof(Word) + 1;
for (; i < wordEnd; i += sizeof(Word)) {
Word a = *(Word*)ap;
Word b = *(Word*)bp;
if (a != b) {
return i + ctzll(a ^ b) / 8;
}
ap += sizeof(Word);
bp += sizeof(Word);
}
for (; i < cl; i++) {
if (*ap != *bp) {
return i;
}
++ap;
++bp;
}
return cl;
}
static inline int commonPrefixLength(const StringRef& a, const StringRef& b) {
return commonPrefixLength(a.begin(), b.begin(), std::min(a.size(), b.size()));
}
static inline int commonPrefixLength(const StringRef& a, const StringRef& b, int skipLen) {
return commonPrefixLength(a.begin() + skipLen, b.begin() + skipLen, std::min(a.size(), b.size()) - skipLen);
}
// This appears to be the fastest version
static int lessOrEqualPowerOfTwo(int n) {
int p;

View File

@ -128,4 +128,25 @@ TEST_CASE("/CompressionUtils/gzipCompression") {
return Void();
}
TEST_CASE("/CompressionUtils/gzipCompression2") {
Arena arena;
const int size = deterministicRandom()->randomInt(512, 1024);
std::string s(size, 'x');
Standalone<StringRef> uncompressed = Standalone<StringRef>(StringRef(s));
printf("Size before: %d\n", (int)uncompressed.size());
Standalone<StringRef> compressed = CompressionUtils::compress(CompressionFilter::GZIP, uncompressed, arena);
ASSERT_NE(compressed.compare(uncompressed), 0);
printf("Size after: %d\n", (int)compressed.size());
// Assert compressed size is less than half.
ASSERT(compressed.size() * 2 < uncompressed.size());
StringRef verify = CompressionUtils::decompress(CompressionFilter::GZIP, compressed, arena);
ASSERT_EQ(verify.compare(uncompressed), 0);
TraceEvent("GzipCompression_Done").log();
return Void();
}
#endif

View File

@ -853,6 +853,40 @@ inline bool operator>=(const StringRef& lhs, const StringRef& rhs) {
return !(lhs < rhs);
}
typedef uint64_t Word;
// Get the number of prefix bytes that are the same between a and b, up to their common length of cl
static inline int commonPrefixLength(uint8_t const* ap, uint8_t const* bp, int cl) {
int i = 0;
const int wordEnd = cl - sizeof(Word) + 1;
for (; i < wordEnd; i += sizeof(Word)) {
Word a = *(Word*)ap;
Word b = *(Word*)bp;
if (a != b) {
return i + ctzll(a ^ b) / 8;
}
ap += sizeof(Word);
bp += sizeof(Word);
}
for (; i < cl; i++) {
if (*ap != *bp) {
return i;
}
++ap;
++bp;
}
return cl;
}
static inline int commonPrefixLength(const StringRef& a, const StringRef& b) {
return commonPrefixLength(a.begin(), b.begin(), std::min(a.size(), b.size()));
}
static inline int commonPrefixLength(const StringRef& a, const StringRef& b, int skipLen) {
return commonPrefixLength(a.begin() + skipLen, b.begin() + skipLen, std::min(a.size(), b.size()) - skipLen);
}
// This trait is used by VectorRef to determine if deep copy constructor should recursively
// call deep copies of each element.
//