Skip to content

Commit 9d8e70a

Browse files
committed
Include checksum in approximate memory usage and updated some comments.
1 parent e3a39a5 commit 9d8e70a

File tree

3 files changed

+119
-8
lines changed

3 files changed

+119
-8
lines changed

table/block_based/block.cc

+13-3
Original file line numberDiff line numberDiff line change
@@ -1091,7 +1091,8 @@ void Block::InitializeDataBlockProtectionInfo(uint8_t protection_bytes_per_key,
10911091
num_keys = iter->NumberOfKeys(block_restart_interval_);
10921092
}
10931093
if (iter->status().ok()) {
1094-
kv_checksum_ = new char[(size_t)num_keys * protection_bytes_per_key];
1094+
checksum_size_ = num_keys * protection_bytes_per_key;
1095+
kv_checksum_ = new char[(size_t)checksum_size_];
10951096
size_t i = 0;
10961097
iter->SeekToFirst();
10971098
while (iter->Valid()) {
@@ -1116,6 +1117,12 @@ void Block::InitializeIndexBlockProtectionInfo(uint8_t protection_bytes_per_key,
11161117
bool index_has_first_key) {
11171118
protection_bytes_per_key_ = 0;
11181119
if (num_restarts_ > 0 && protection_bytes_per_key > 0) {
1120+
// Note that `global_seqno` and `key_includes_seq` are hardcoded here. They
1121+
// do not impact how the index block is parsed. During checksum
1122+
// construction/verification, we use the entire key buffer from
1123+
// raw_key_.GetKey() returned by iter->key() as the `key` part of key-value
1124+
// checksum, and the content of this buffer do not change for different
1125+
// values of `global_seqno` or `key_includes_seq`.
11191126
std::unique_ptr<IndexBlockIter> iter{NewIndexIterator(
11201127
raw_ucmp, kDisableGlobalSequenceNumber /* global_seqno */, nullptr,
11211128
nullptr /* Statistics */, true /* total_order_seek */,
@@ -1130,7 +1137,8 @@ void Block::InitializeIndexBlockProtectionInfo(uint8_t protection_bytes_per_key,
11301137
num_keys = iter->NumberOfKeys(block_restart_interval_);
11311138
}
11321139
if (iter->status().ok()) {
1133-
kv_checksum_ = new char[(size_t)num_keys * protection_bytes_per_key];
1140+
checksum_size_ = num_keys * protection_bytes_per_key;
1141+
kv_checksum_ = new char[(size_t)checksum_size_];
11341142
iter->SeekToFirst();
11351143
size_t i = 0;
11361144
while (iter->Valid()) {
@@ -1163,7 +1171,8 @@ void Block::InitializeMetaIndexBlockProtectionInfo(
11631171
num_keys = iter->NumberOfKeys(block_restart_interval_);
11641172
}
11651173
if (iter->status().ok()) {
1166-
kv_checksum_ = new char[(size_t)num_keys * protection_bytes_per_key];
1174+
checksum_size_ = num_keys * protection_bytes_per_key;
1175+
kv_checksum_ = new char[(size_t)checksum_size_];
11671176
iter->SeekToFirst();
11681177
size_t i = 0;
11691178
while (iter->Valid()) {
@@ -1275,6 +1284,7 @@ size_t Block::ApproximateMemoryUsage() const {
12751284
if (read_amp_bitmap_) {
12761285
usage += read_amp_bitmap_->ApproximateMemoryUsage();
12771286
}
1287+
usage += checksum_size_;
12781288
return usage;
12791289
}
12801290

table/block_based/block.h

+1
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,7 @@ class Block {
278278
std::unique_ptr<BlockReadAmpBitmap> read_amp_bitmap_;
279279
DataBlockHashIndex data_block_hash_index_;
280280
char* kv_checksum_{nullptr};
281+
uint32_t checksum_size_{0};
281282
// Used by block iterators to calculate current key index within a block
282283
uint32_t block_restart_interval_{0};
283284
uint8_t protection_bytes_per_key_{0};

table/block_based/block_test.cc

+105-5
Original file line numberDiff line numberDiff line change
@@ -746,11 +746,6 @@ TEST_F(BlockPerKVChecksumTest, UnsupportedOptionValue) {
746746
TEST_F(BlockPerKVChecksumTest, InitializeProtectionInfo) {
747747
// Make sure that the checksum construction code path does not break
748748
// when the block is itself already corrupted.
749-
std::string invalid_content = "1";
750-
Slice raw_block = invalid_content;
751-
BlockContents contents;
752-
contents.data = raw_block;
753-
754749
Options options = Options();
755750
BlockBasedTableOptions tbo;
756751
uint8_t protection_bytes_per_key = 8;
@@ -759,13 +754,21 @@ TEST_F(BlockPerKVChecksumTest, InitializeProtectionInfo) {
759754
protection_bytes_per_key, options.comparator};
760755

761756
{
757+
std::string invalid_content = "1";
758+
Slice raw_block = invalid_content;
759+
BlockContents contents;
760+
contents.data = raw_block;
762761
std::unique_ptr<Block_kData> data_block;
763762
create_context.Create(&data_block, std::move(contents));
764763
std::unique_ptr<DataBlockIter> iter{data_block->NewDataIterator(
765764
options.comparator, kDisableGlobalSequenceNumber)};
766765
ASSERT_TRUE(iter->status().IsCorruption());
767766
}
768767
{
768+
std::string invalid_content = "1";
769+
Slice raw_block = invalid_content;
770+
BlockContents contents;
771+
contents.data = raw_block;
769772
std::unique_ptr<Block_kIndex> index_block;
770773
create_context.Create(&index_block, std::move(contents));
771774
std::unique_ptr<IndexBlockIter> iter{index_block->NewIndexIterator(
@@ -774,13 +777,110 @@ TEST_F(BlockPerKVChecksumTest, InitializeProtectionInfo) {
774777
ASSERT_TRUE(iter->status().IsCorruption());
775778
}
776779
{
780+
std::string invalid_content = "1";
781+
Slice raw_block = invalid_content;
782+
BlockContents contents;
783+
contents.data = raw_block;
777784
std::unique_ptr<Block_kMetaIndex> meta_block;
778785
create_context.Create(&meta_block, std::move(contents));
779786
std::unique_ptr<MetaBlockIter> iter{meta_block->NewMetaIterator(true)};
780787
ASSERT_TRUE(iter->status().IsCorruption());
781788
}
782789
}
783790

791+
TEST_F(BlockPerKVChecksumTest, ApproximateMemory) {
792+
// Tests that ApproximateMemoryUsage() includes memory used by block kv
793+
// checksum.
794+
const int kNumRecords = 20;
795+
std::vector<std::string> keys;
796+
std::vector<std::string> values;
797+
GenerateRandomKVs(&keys, &values, 0, kNumRecords, 1 /* step */,
798+
24 /* padding_size */);
799+
std::unique_ptr<BlockBuilder> builder;
800+
auto generate_block_content = [&]() {
801+
builder = std::make_unique<BlockBuilder>(16 /* restart_interval */);
802+
for (int i = 0; i < kNumRecords; ++i) {
803+
builder->Add(keys[i], values[i]);
804+
}
805+
Slice raw_block = builder->Finish();
806+
BlockContents contents;
807+
contents.data = raw_block;
808+
return contents;
809+
};
810+
811+
Options options = Options();
812+
BlockBasedTableOptions tbo;
813+
uint8_t protection_bytes_per_key = 8;
814+
BlockCreateContext with_checksum_create_context{
815+
&tbo,
816+
nullptr /* statistics */,
817+
false /* using_zstd */,
818+
protection_bytes_per_key,
819+
options.comparator,
820+
true /* index_value_is_full */};
821+
BlockCreateContext create_context{
822+
&tbo, nullptr /* statistics */, false /* using_zstd */,
823+
0, options.comparator, true /* index_value_is_full */};
824+
size_t checksum_size = protection_bytes_per_key * kNumRecords;
825+
826+
{
827+
std::unique_ptr<Block_kData> data_block;
828+
create_context.Create(&data_block, generate_block_content());
829+
std::unique_ptr<Block_kData> with_checksum_data_block;
830+
with_checksum_create_context.Create(&with_checksum_data_block,
831+
generate_block_content());
832+
ASSERT_EQ(with_checksum_data_block->ApproximateMemoryUsage() -
833+
data_block->ApproximateMemoryUsage(),
834+
checksum_size);
835+
}
836+
837+
{
838+
std::unique_ptr<Block_kData> meta_block;
839+
create_context.Create(&meta_block, generate_block_content());
840+
std::unique_ptr<Block_kData> with_checksum_meta_block;
841+
with_checksum_create_context.Create(&with_checksum_meta_block,
842+
generate_block_content());
843+
ASSERT_EQ(with_checksum_meta_block->ApproximateMemoryUsage() -
844+
meta_block->ApproximateMemoryUsage(),
845+
checksum_size);
846+
}
847+
848+
{
849+
// Index block has different contents.
850+
std::vector<std::string> separators;
851+
std::vector<BlockHandle> block_handles;
852+
std::vector<std::string> first_keys;
853+
GenerateRandomIndexEntries(&separators, &block_handles, &first_keys,
854+
kNumRecords);
855+
auto generate_index_content = [&]() {
856+
builder = std::make_unique<BlockBuilder>(16 /* restart_interval */);
857+
BlockHandle last_encoded_handle;
858+
for (int i = 0; i < kNumRecords; ++i) {
859+
IndexValue entry(block_handles[i], first_keys[i]);
860+
std::string encoded_entry;
861+
std::string delta_encoded_entry;
862+
entry.EncodeTo(&encoded_entry, false, nullptr);
863+
last_encoded_handle = entry.handle;
864+
const Slice delta_encoded_entry_slice(delta_encoded_entry);
865+
builder->Add(separators[i], encoded_entry, &delta_encoded_entry_slice);
866+
}
867+
Slice raw_block = builder->Finish();
868+
BlockContents contents;
869+
contents.data = raw_block;
870+
return contents;
871+
};
872+
873+
std::unique_ptr<Block_kIndex> index_block;
874+
create_context.Create(&index_block, generate_index_content());
875+
std::unique_ptr<Block_kIndex> with_checksum_index_block;
876+
with_checksum_create_context.Create(&with_checksum_index_block,
877+
generate_index_content());
878+
ASSERT_EQ(with_checksum_index_block->ApproximateMemoryUsage() -
879+
index_block->ApproximateMemoryUsage(),
880+
checksum_size);
881+
}
882+
}
883+
784884
std::string GetDataBlockIndexTypeStr(
785885
BlockBasedTableOptions::DataBlockIndexType t) {
786886
return t == BlockBasedTableOptions::DataBlockIndexType::kDataBlockBinarySearch

0 commit comments

Comments
 (0)