mirror of
https://github.com/facebook/rocksdb.git
synced 2026-07-07 14:47:40 +08:00
Use format_version=7 by default, fix perf bug (#14239)
Summary: Since it's been > 6 months and we have production uses, migrate to fv=7 by default. One unit test needed an update for the change to table properties with fv=7. On making this change, PresetCompressionDictTest tests detected extra memory usage by decompressing LZ4 with dictionary compression. This turned out to be a bug in `std::find` usage that led to using the ZSTD-optimized decompressor (with digested dictionary usage) in cases where it is not needed. I've fixed the bug and improved the unit tests that found the bug. Pull Request resolved: https://github.com/facebook/rocksdb/pull/14239 Test Plan: existing tests, including format compatible CI job (updated, and run locally with SHORT_TEST=1) Reviewed By: hx235 Differential Revision: D90728697 Pulled By: pdillinger fbshipit-source-id: 8f1a0e9ca59a88c18eaa4cdfdea00309175ce30a
This commit is contained in:
committed by
meta-codesync[bot]
parent
eb5e1a2d1f
commit
a6af317476
@@ -433,8 +433,9 @@ TEST_F(CompactFilesTest, SentinelCompressionType) {
|
||||
ROCKSDB_NAMESPACE::TablePropertiesCollection all_tables_props;
|
||||
ASSERT_OK(db->GetPropertiesOfAllTables(&all_tables_props));
|
||||
for (const auto& name_and_table_props : all_tables_props) {
|
||||
ASSERT_EQ(CompressionTypeToString(CompressionType::kZlibCompression),
|
||||
name_and_table_props.second->compression_name);
|
||||
// As of format_version 7, more elaborate information is encoded into the
|
||||
// compression_name property
|
||||
ASSERT_EQ("BuiltinV2;02;", name_and_table_props.second->compression_name);
|
||||
}
|
||||
delete db;
|
||||
}
|
||||
|
||||
@@ -593,7 +593,7 @@ struct BlockBasedTableOptions {
|
||||
// validation and sufficient time and number of releases have elapsed
|
||||
// (6 months recommended) to ensure a clean downgrade/revert path for users
|
||||
// who might only upgrade a few times per year.
|
||||
uint32_t format_version = 6;
|
||||
uint32_t format_version = 7;
|
||||
|
||||
// Store index blocks on disk in compressed format. Changing this option to
|
||||
// false will avoid the overhead of decompression if index blocks are evicted
|
||||
|
||||
@@ -37,7 +37,7 @@ public class BlockBasedTableConfig extends TableFormatConfig {
|
||||
wholeKeyFiltering = true;
|
||||
verifyCompression = false;
|
||||
readAmpBytesPerBit = 0;
|
||||
formatVersion = 6;
|
||||
formatVersion = 7;
|
||||
enableIndexCompression = true;
|
||||
blockAlign = false;
|
||||
superBlockAlignmentSize = 0;
|
||||
|
||||
@@ -137,7 +137,7 @@ EOF
|
||||
|
||||
# To check for DB forward compatibility with loading options (old version
|
||||
# reading data from new), as well as backward compatibility
|
||||
declare -a db_forward_with_options_refs=("8.6.fb" "8.7.fb" "8.8.fb" "8.9.fb" "8.10.fb" "8.11.fb" "9.0.fb" "9.1.fb" "9.2.fb" "9.3.fb" "9.4.fb" "9.5.fb" "9.6.fb" "9.7.fb" "9.8.fb" "9.9.fb" "9.10.fb" "9.11.fb" "10.0.fb" "10.1.fb" "10.2.fb" "10.3.fb" "10.4.fb" "10.5.fb" "10.6.fb" "10.7.fb" "10.8.fb" "10.9.fb" "10.10.fb")
|
||||
declare -a db_forward_with_options_refs=("10.4.fb" "10.5.fb" "10.6.fb" "10.7.fb" "10.8.fb" "10.9.fb" "10.10.fb")
|
||||
# To check for DB forward compatibility without loading options (in addition
|
||||
# to the "with loading options" set), as well as backward compatibility
|
||||
declare -a db_forward_no_options_refs=() # N/A at the moment
|
||||
@@ -145,7 +145,7 @@ declare -a db_forward_no_options_refs=() # N/A at the moment
|
||||
# To check for SST ingestion backward compatibility (new version reading
|
||||
# data from old) (ldb ingest_extern_sst added in 5.16.x, back-ported to
|
||||
# 5.14.x, 5.15.x)
|
||||
declare -a ext_backward_only_refs=("5.14.fb" "5.15.fb" "5.16.fb" "5.17.fb" "5.18.fb" "6.0.fb" "6.1.fb" "6.2.fb" "6.3.fb" "6.4.fb" "6.5.fb" "6.6.fb" "6.7.fb" "6.8.fb" "6.9.fb" "6.10.fb" "6.11.fb" "6.12.fb" "6.13.fb" "6.14.fb" "6.15.fb" "6.16.fb" "6.17.fb" "6.18.fb" "6.19.fb" "6.20.fb" "6.21.fb" "6.22.fb" "6.23.fb" "6.24.fb" "6.25.fb" "6.26.fb" "6.27.fb" "6.28.fb" "6.29.fb" "7.0.fb" "7.1.fb" "7.2.fb" "7.3.fb" "7.4.fb" "7.5.fb" "7.6.fb" "7.7.fb" "7.8.fb" "7.9.fb" "7.10.fb" "8.0.fb" "8.1.fb" "8.2.fb" "8.3.fb" "8.4.fb" "8.5.fb")
|
||||
declare -a ext_backward_only_refs=("5.14.fb" "5.15.fb" "5.16.fb" "5.17.fb" "5.18.fb" "6.0.fb" "6.1.fb" "6.2.fb" "6.3.fb" "6.4.fb" "6.5.fb" "6.6.fb" "6.7.fb" "6.8.fb" "6.9.fb" "6.10.fb" "6.11.fb" "6.12.fb" "6.13.fb" "6.14.fb" "6.15.fb" "6.16.fb" "6.17.fb" "6.18.fb" "6.19.fb" "6.20.fb" "6.21.fb" "6.22.fb" "6.23.fb" "6.24.fb" "6.25.fb" "6.26.fb" "6.27.fb" "6.28.fb" "6.29.fb" "7.0.fb" "7.1.fb" "7.2.fb" "7.3.fb" "7.4.fb" "7.5.fb" "7.6.fb" "7.7.fb" "7.8.fb" "7.9.fb" "7.10.fb" "8.0.fb" "8.1.fb" "8.2.fb" "8.3.fb" "8.4.fb" "8.5.fb" "8.6.fb" "8.7.fb" "8.8.fb" "8.9.fb" "8.10.fb" "8.11.fb" "9.0.fb" "9.1.fb" "9.2.fb" "9.3.fb" "9.4.fb" "9.5.fb" "9.6.fb" "9.7.fb" "9.8.fb" "9.9.fb" "9.10.fb" "9.11.fb" "10.0.fb" "10.1.fb" "10.2.fb" "10.3.fb")
|
||||
# To check for SST ingestion forward compatibility (old version reading
|
||||
# data from new) as well as backward compatibility
|
||||
declare -a ext_forward_refs=("${db_forward_no_options_refs[@]}" "${db_forward_with_options_refs[@]}")
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
* The new default for `BlockBasedTableOptions::format_version` is 7, which has been supported since RocksDB 10.4.0 and is required in order to use CompressionManagers supporting custom compression types.
|
||||
@@ -0,0 +1 @@
|
||||
* Fixed a small performance bug with `format_version=7` when decompressing formats other than Snappy and ZSTD.
|
||||
+4
-1
@@ -1632,10 +1632,13 @@ class BuiltinCompressionManagerV2 final : public CompressionManager {
|
||||
return nullptr;
|
||||
} else if (types_begin + 1 == types_end &&
|
||||
*types_begin == kSnappyCompression) {
|
||||
// Exclusively Snappy
|
||||
return GetSnappyDecompressor();
|
||||
} else if (std::find(types_begin, types_end, kZSTD)) {
|
||||
} else if (std::find(types_begin, types_end, kZSTD) != types_end) {
|
||||
// Includes ZSTD
|
||||
return GetZstdDecompressor();
|
||||
} else {
|
||||
// Everything else
|
||||
return GetGeneralDecompressor();
|
||||
}
|
||||
}
|
||||
|
||||
+36
-40
@@ -583,17 +583,15 @@ TEST_P(PresetCompressionDictTest, Flush) {
|
||||
ASSERT_GT(
|
||||
TestGetTickerCount(options, BLOCK_CACHE_COMPRESSION_DICT_BYTES_INSERT),
|
||||
0);
|
||||
// TODO(ajkr): fix the below assertion to work with ZSTD. The expectation on
|
||||
// number of bytes needs to be adjusted in case the cached block is in
|
||||
// ZSTD's digested dictionary format.
|
||||
if (compression_type_ != kZSTD) {
|
||||
// Although we limited buffering to `kBlockLen`, there may be up to two
|
||||
// blocks of data included in the dictionary since we only check limit
|
||||
// after each block is built.
|
||||
ASSERT_LE(TestGetTickerCount(options,
|
||||
BLOCK_CACHE_COMPRESSION_DICT_BYTES_INSERT),
|
||||
2 * kBlockLen);
|
||||
}
|
||||
ASSERT_EQ(TestGetTickerCount(options, BLOCK_CACHE_COMPRESSION_DICT_ADD), 1);
|
||||
// Although we stop buffering after `kBlockLen` bytes, there may be up to
|
||||
// two blocks of data included in the dictionary since we only check limit
|
||||
// after each block is built. And because block cache charges for bytes used
|
||||
// by ZSTD's digested dictionary, we need a larger factor for the memory
|
||||
// overheads in that case.
|
||||
ASSERT_LE(
|
||||
TestGetTickerCount(options, BLOCK_CACHE_COMPRESSION_DICT_BYTES_INSERT),
|
||||
(compression_type_ == kZSTD ? 10 : 2) * kBlockLen);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -642,8 +640,9 @@ TEST_P(PresetCompressionDictTest, CompactNonBottommost) {
|
||||
}
|
||||
ASSERT_EQ("2,0,1", FilesPerLevel(0));
|
||||
|
||||
uint64_t prev_compression_dict_bytes_inserted =
|
||||
TestGetTickerCount(options, BLOCK_CACHE_COMPRESSION_DICT_BYTES_INSERT);
|
||||
PopTicker(options, BLOCK_CACHE_COMPRESSION_DICT_BYTES_INSERT);
|
||||
PopTicker(options, BLOCK_CACHE_COMPRESSION_DICT_ADD);
|
||||
|
||||
// This L0->L1 compaction merges the two L0 files into L1. The produced L1
|
||||
// file is not bottommost due to the existing L2 file covering the same key-
|
||||
// range.
|
||||
@@ -655,22 +654,20 @@ TEST_P(PresetCompressionDictTest, CompactNonBottommost) {
|
||||
if (bottommost_) {
|
||||
ASSERT_EQ(
|
||||
TestGetTickerCount(options, BLOCK_CACHE_COMPRESSION_DICT_BYTES_INSERT),
|
||||
prev_compression_dict_bytes_inserted);
|
||||
0);
|
||||
} else {
|
||||
ASSERT_GT(
|
||||
TestGetTickerCount(options, BLOCK_CACHE_COMPRESSION_DICT_BYTES_INSERT),
|
||||
prev_compression_dict_bytes_inserted);
|
||||
// TODO(ajkr): fix the below assertion to work with ZSTD. The expectation on
|
||||
// number of bytes needs to be adjusted in case the cached block is in
|
||||
// ZSTD's digested dictionary format.
|
||||
if (compression_type_ != kZSTD) {
|
||||
// Although we limited buffering to `kBlockLen`, there may be up to two
|
||||
// blocks of data included in the dictionary since we only check limit
|
||||
// after each block is built.
|
||||
ASSERT_LE(TestGetTickerCount(options,
|
||||
BLOCK_CACHE_COMPRESSION_DICT_BYTES_INSERT),
|
||||
prev_compression_dict_bytes_inserted + 2 * kBlockLen);
|
||||
}
|
||||
0);
|
||||
ASSERT_EQ(TestGetTickerCount(options, BLOCK_CACHE_COMPRESSION_DICT_ADD), 1);
|
||||
// Although we stop buffering after `kBlockLen` bytes, there may be up to
|
||||
// two blocks of data included in the dictionary since we only check limit
|
||||
// after each block is built. And because block cache charges for bytes used
|
||||
// by ZSTD's digested dictionary, we need a larger factor for the memory
|
||||
// overheads in that case.
|
||||
ASSERT_LE(
|
||||
TestGetTickerCount(options, BLOCK_CACHE_COMPRESSION_DICT_BYTES_INSERT),
|
||||
(compression_type_ == kZSTD ? 10 : 2) * kBlockLen);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -713,25 +710,24 @@ TEST_P(PresetCompressionDictTest, CompactBottommost) {
|
||||
}
|
||||
ASSERT_EQ("2", FilesPerLevel(0));
|
||||
|
||||
uint64_t prev_compression_dict_bytes_inserted =
|
||||
TestGetTickerCount(options, BLOCK_CACHE_COMPRESSION_DICT_BYTES_INSERT);
|
||||
PopTicker(options, BLOCK_CACHE_COMPRESSION_DICT_BYTES_INSERT);
|
||||
PopTicker(options, BLOCK_CACHE_COMPRESSION_DICT_ADD);
|
||||
|
||||
CompactRangeOptions cro;
|
||||
ASSERT_OK(db_->CompactRange(cro, nullptr, nullptr));
|
||||
ASSERT_EQ("0,1", FilesPerLevel(0));
|
||||
ASSERT_GT(
|
||||
TestGetTickerCount(options, BLOCK_CACHE_COMPRESSION_DICT_BYTES_INSERT),
|
||||
prev_compression_dict_bytes_inserted);
|
||||
// TODO(ajkr): fix the below assertion to work with ZSTD. The expectation on
|
||||
// number of bytes needs to be adjusted in case the cached block is in ZSTD's
|
||||
// digested dictionary format.
|
||||
if (compression_type_ != kZSTD) {
|
||||
// Although we limited buffering to `kBlockLen`, there may be up to two
|
||||
// blocks of data included in the dictionary since we only check limit after
|
||||
// each block is built.
|
||||
ASSERT_LE(
|
||||
TestGetTickerCount(options, BLOCK_CACHE_COMPRESSION_DICT_BYTES_INSERT),
|
||||
prev_compression_dict_bytes_inserted + 2 * kBlockLen);
|
||||
}
|
||||
0);
|
||||
ASSERT_EQ(TestGetTickerCount(options, BLOCK_CACHE_COMPRESSION_DICT_ADD), 1);
|
||||
// Although we stop buffering after `kBlockLen` bytes, there may be up to
|
||||
// two blocks of data included in the dictionary since we only check limit
|
||||
// after each block is built. And because block cache charges for bytes used
|
||||
// by ZSTD's digested dictionary, we need a larger factor for the memory
|
||||
// overheads in that case.
|
||||
ASSERT_LE(
|
||||
TestGetTickerCount(options, BLOCK_CACHE_COMPRESSION_DICT_BYTES_INSERT),
|
||||
(compression_type_ == kZSTD ? 10 : 2) * kBlockLen);
|
||||
}
|
||||
|
||||
class CompactionCompressionListener : public EventListener {
|
||||
|
||||
Reference in New Issue
Block a user