Skip to content

Commit 2e89ff5

Browse files
committed
init
1 parent da2c3c0 commit 2e89ff5

23 files changed

+580
-109
lines changed

db/compaction/compaction_job.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,8 @@ const char* GetCompactionReasonString(CompactionReason compaction_reason) {
103103
return "RoundRobinTtl";
104104
case CompactionReason::kRefitLevel:
105105
return "RefitLevel";
106+
case CompactionReason::kReadTriggered:
107+
return "ReadTriggered";
106108
case CompactionReason::kNumOfReasons:
107109
// fall through
108110
default:

db/compaction/compaction_picker_level.cc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ bool LevelCompactionPicker::NeedsCompaction(
3636
if (!vstorage->FilesMarkedForForcedBlobGC().empty()) {
3737
return true;
3838
}
39+
if (!vstorage->ReadTriggeredCompactionFiles().empty()) {
40+
return true;
41+
}
3942
for (int i = 0; i <= vstorage->MaxInputLevel(); i++) {
4043
if (vstorage->CompactionScore(i) >= 1) {
4144
return true;
@@ -325,6 +328,14 @@ void LevelCompactionBuilder::SetupInitialFiles() {
325328
compaction_reason_ = CompactionReason::kForcedBlobGC;
326329
return;
327330
}
331+
332+
// Read-triggered compaction
333+
PickFileToCompact(vstorage_->ReadTriggeredCompactionFiles(),
334+
CompactToNextLevel::kYes);
335+
if (!start_level_inputs_.empty()) {
336+
compaction_reason_ = CompactionReason::kReadTriggered;
337+
return;
338+
}
328339
}
329340

330341
bool LevelCompactionBuilder::SetupOtherL0FilesIfNeeded() {

db/compaction/compaction_picker_test.cc

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -982,6 +982,150 @@ TEST_F(CompactionPickerTest, UniversalIncrementalSpace1) {
982982
ASSERT_EQ(14U, compaction->input(1, 3)->fd.GetNumber());
983983
}
984984

985+
TEST_F(CompactionPickerTest, ReadTriggeredCompactionDisabled) {
986+
NewVersionStorage(6, kCompactionStyleLevel);
987+
// threshold=0 means disabled, no files should be marked
988+
mutable_cf_options_.read_triggered_compaction_threshold = 0.0;
989+
Add(0, 1U, "100", "200", 1000U);
990+
file_map_[1U].first->stats.num_reads_sampled.store(999999);
991+
UpdateVersionStorageInfo();
992+
ASSERT_TRUE(vstorage_->ReadTriggeredCompactionFiles().empty());
993+
}
994+
995+
TEST_F(CompactionPickerTest, ReadTriggeredCompactionBelowThreshold) {
996+
NewVersionStorage(6, kCompactionStyleLevel);
997+
mutable_cf_options_.read_triggered_compaction_threshold = 1.0;
998+
// file_size=1000, reads=500 => reads_per_byte=0.5 < 1.0
999+
Add(0, 1U, "100", "200", 1000U);
1000+
file_map_[1U].first->stats.num_reads_sampled.store(500);
1001+
UpdateVersionStorageInfo();
1002+
ASSERT_TRUE(vstorage_->ReadTriggeredCompactionFiles().empty());
1003+
}
1004+
1005+
TEST_F(CompactionPickerTest, ReadTriggeredCompactionAboveThreshold) {
1006+
NewVersionStorage(6, kCompactionStyleLevel);
1007+
mutable_cf_options_.read_triggered_compaction_threshold = 0.5;
1008+
// file_size=1000, reads=600 => reads_per_byte=0.6 > 0.5
1009+
Add(0, 1U, "100", "200", 1000U);
1010+
file_map_[1U].first->stats.num_reads_sampled.store(600);
1011+
// file_size=1000, reads=300 => reads_per_byte=0.3 < 0.5 (not marked)
1012+
Add(1, 2U, "300", "400", 1000U);
1013+
file_map_[2U].first->stats.num_reads_sampled.store(300);
1014+
// file_size=1000, reads=800 => reads_per_byte=0.8 > 0.5 (hottest)
1015+
Add(2, 3U, "500", "600", 1000U);
1016+
file_map_[3U].first->stats.num_reads_sampled.store(800);
1017+
// Add a file at the bottom so L2 is not the last non-empty level
1018+
Add(4, 4U, "700", "800", 1000U);
1019+
UpdateVersionStorageInfo();
1020+
1021+
const auto& marked = vstorage_->ReadTriggeredCompactionFiles();
1022+
ASSERT_EQ(marked.size(), 2);
1023+
// Sorted by reads_per_byte descending: file 3 (0.8) then file 1 (0.6)
1024+
ASSERT_EQ(marked[0].second->fd.GetNumber(), 3U);
1025+
ASSERT_EQ(marked[1].second->fd.GetNumber(), 1U);
1026+
}
1027+
1028+
TEST_F(CompactionPickerTest, NeedsCompactionReadTriggered) {
1029+
NewVersionStorage(6, kCompactionStyleLevel);
1030+
mutable_cf_options_.read_triggered_compaction_threshold = 0.1;
1031+
Add(1, 1U, "100", "200", 1000U);
1032+
file_map_[1U].first->stats.num_reads_sampled.store(500);
1033+
Add(3, 2U, "300", "400", 1000U);
1034+
UpdateVersionStorageInfo();
1035+
1036+
ASSERT_FALSE(vstorage_->ReadTriggeredCompactionFiles().empty());
1037+
ASSERT_TRUE(level_compaction_picker.NeedsCompaction(vstorage_.get()));
1038+
}
1039+
1040+
TEST_F(CompactionPickerTest, ReadTriggeredPicksFile) {
1041+
NewVersionStorage(6, kCompactionStyleLevel);
1042+
mutable_cf_options_.read_triggered_compaction_threshold = 0.1;
1043+
Add(1, 1U, "100", "200", 1000U);
1044+
file_map_[1U].first->stats.num_reads_sampled.store(500);
1045+
Add(3, 2U, "300", "400", 1000U);
1046+
UpdateVersionStorageInfo();
1047+
1048+
std::unique_ptr<Compaction> compaction(level_compaction_picker.PickCompaction(
1049+
cf_name_, mutable_cf_options_, mutable_db_options_,
1050+
/*existing_snapshots=*/{}, /*snapshot_checker=*/nullptr, vstorage_.get(),
1051+
&log_buffer_, /*full_history_ts_low=*/""));
1052+
ASSERT_TRUE(compaction.get() != nullptr);
1053+
ASSERT_EQ(compaction->compaction_reason(), CompactionReason::kReadTriggered);
1054+
}
1055+
1056+
TEST_F(CompactionPickerTest, UniversalReadTriggeredCompaction) {
1057+
const uint64_t kFileSize = 100000;
1058+
1059+
mutable_cf_options_.read_triggered_compaction_threshold = 0.001;
1060+
// Set trigger high so size amp / sorted run pickers don't fire
1061+
mutable_cf_options_.level0_file_num_compaction_trigger = 10;
1062+
UniversalCompactionPicker universal_compaction_picker(ioptions_, &icmp_);
1063+
1064+
NewVersionStorage(5, kCompactionStyleUniversal);
1065+
1066+
// Hot file at L2 with data at L4 below it
1067+
Add(0, 1U, "150", "200", kFileSize, 0, 500, 550);
1068+
Add(2, 2U, "301", "350", kFileSize, 0, 201, 250);
1069+
Add(4, 3U, "301", "400", kFileSize, 0, 101, 150);
1070+
1071+
// Mark file 2 (L2) as having high reads
1072+
file_map_[2U].first->stats.num_reads_sampled.store(kFileSize);
1073+
UpdateVersionStorageInfo();
1074+
1075+
ASSERT_TRUE(universal_compaction_picker.NeedsCompaction(vstorage_.get()));
1076+
1077+
std::unique_ptr<Compaction> compaction(
1078+
universal_compaction_picker.PickCompaction(
1079+
cf_name_, mutable_cf_options_, mutable_db_options_,
1080+
/*existing_snapshots=*/{}, /*snapshot_checker=*/nullptr,
1081+
vstorage_.get(), &log_buffer_, /*full_history_ts_low=*/""));
1082+
1083+
ASSERT_TRUE(compaction);
1084+
ASSERT_EQ(compaction->compaction_reason(), CompactionReason::kReadTriggered);
1085+
ASSERT_EQ(compaction->start_level(), 2);
1086+
ASSERT_EQ(compaction->output_level(), 4);
1087+
}
1088+
1089+
TEST_F(CompactionPickerTest, ReadTriggeredSkipsLastLevel) {
1090+
const uint64_t kFileSize = 100000;
1091+
1092+
mutable_cf_options_.read_triggered_compaction_threshold = 0.001;
1093+
mutable_cf_options_.level0_file_num_compaction_trigger = 10;
1094+
UniversalCompactionPicker universal_compaction_picker(ioptions_, &icmp_);
1095+
1096+
NewVersionStorage(5, kCompactionStyleUniversal);
1097+
1098+
Add(0, 1U, "150", "200", kFileSize, 0, 500, 550);
1099+
Add(4, 3U, "301", "350", kFileSize, 0, 101, 150);
1100+
1101+
// File 3 is at the last non-empty level — should NOT be marked for
1102+
// read-triggered compaction. Bottommost file cleanup is handled
1103+
// separately by ComputeBottommostFilesMarkedForCompaction().
1104+
file_map_[3U].first->stats.num_reads_sampled.store(kFileSize);
1105+
UpdateVersionStorageInfo();
1106+
1107+
ASSERT_TRUE(vstorage_->ReadTriggeredCompactionFiles().empty());
1108+
}
1109+
1110+
TEST_F(CompactionPickerTest, UniversalReadTriggeredNoPickWhenNotMarked) {
1111+
const uint64_t kFileSize = 100000;
1112+
1113+
mutable_cf_options_.read_triggered_compaction_threshold = 0.001;
1114+
UniversalCompactionPicker universal_compaction_picker(ioptions_, &icmp_);
1115+
1116+
NewVersionStorage(5, kCompactionStyleUniversal);
1117+
1118+
Add(0, 1U, "150", "200", kFileSize, 0, 500, 550);
1119+
Add(4, 3U, "301", "350", kFileSize, 0, 101, 150);
1120+
1121+
// No reads on any file
1122+
UpdateVersionStorageInfo();
1123+
1124+
ASSERT_TRUE(vstorage_->ReadTriggeredCompactionFiles().empty());
1125+
// Not enough sorted runs to trigger compaction either
1126+
ASSERT_FALSE(universal_compaction_picker.NeedsCompaction(vstorage_.get()));
1127+
}
1128+
9851129
TEST_F(CompactionPickerTest, UniversalIncrementalSpace2) {
9861130
const uint64_t kFileSize = 100000;
9871131

0 commit comments

Comments
 (0)