Skip to content

Commit 5e3aeb5

Browse files
committed
An initial implementation of kCompactionStopStyleSimilarSize for universal compaction
1 parent b1194f4 commit 5e3aeb5

File tree

2 files changed

+112
-2
lines changed

2 files changed

+112
-2
lines changed

db/compaction_picker.cc

+20-2
Original file line numberDiff line numberDiff line change
@@ -683,14 +683,32 @@ Compaction* UniversalCompactionPicker::PickCompactionUniversalReadAmp(
683683
if (f->being_compacted) {
684684
break;
685685
}
686-
// pick files if the total candidate file size (increased by the
686+
// Pick files if the total/last candidate file size (increased by the
687687
// specified ratio) is still larger than the next candidate file.
688+
// candidate_size is the total size of files picked so far with the
689+
// default kCompactionStopStyleTotalSize; with
690+
// kCompactionStopStyleSimilarSize, it's simply the size of the last
691+
// picked file.
688692
uint64_t sz = (candidate_size * (100L + ratio)) /100;
689693
if (sz < f->file_size) {
690694
break;
695+
}
696+
if (options_->compaction_options_universal.stop_style == kCompactionStopStyleSimilarSize) {
697+
// Similar-size stopping rule: also check the last picked file isn't
698+
// far larger than the next candidate file.
699+
sz = (f->file_size * (100L + ratio)) / 100;
700+
if (sz < candidate_size) {
701+
// If the small file we've encountered begins a run of similar-size
702+
// files, we'll pick them up on a future iteration of the outer
703+
// loop. If it's some lonely straggler, it'll eventually get picked
704+
// by the last-resort read amp strategy which disregards size ratios.
705+
break;
706+
}
707+
candidate_size = f->file_size;
708+
} else { // default kCompactionStopStyleTotalSize
709+
candidate_size += f->file_size;
691710
}
692711
candidate_count++;
693-
candidate_size += f->file_size;
694712
}
695713

696714
// Found a series of consecutive files that need compaction.

db/db_test.cc

+92
Original file line numberDiff line numberDiff line change
@@ -2043,6 +2043,98 @@ TEST(DBTest, UniversalCompactionOptions) {
20432043
}
20442044
}
20452045

2046+
TEST(DBTest, UniversalCompactionStopStyleSimilarSize) {
2047+
Options options = CurrentOptions();
2048+
options.compaction_style = kCompactionStyleUniversal;
2049+
options.write_buffer_size = 100<<10; //100KB
2050+
// trigger compaction if there are >= 4 files
2051+
options.level0_file_num_compaction_trigger = 4;
2052+
options.compaction_options_universal.size_ratio = 10;
2053+
options.compaction_options_universal.stop_style = kCompactionStopStyleSimilarSize;
2054+
Reopen(&options);
2055+
2056+
Random rnd(301);
2057+
int key_idx = 0;
2058+
2059+
// Stage 1:
2060+
// Generate a set of files at level 0, but don't trigger level-0
2061+
// compaction.
2062+
for (int num = 0;
2063+
num < options.level0_file_num_compaction_trigger-1;
2064+
num++) {
2065+
// Write 120KB (12 values, each 10K)
2066+
for (int i = 0; i < 12; i++) {
2067+
ASSERT_OK(Put(Key(key_idx), RandomString(&rnd, 10000)));
2068+
key_idx++;
2069+
}
2070+
dbfull()->TEST_WaitForFlushMemTable();
2071+
ASSERT_EQ(NumTableFilesAtLevel(0), num + 1);
2072+
}
2073+
2074+
// Generate one more file at level-0, which should trigger level-0
2075+
// compaction.
2076+
for (int i = 0; i < 12; i++) {
2077+
ASSERT_OK(Put(Key(key_idx), RandomString(&rnd, 10000)));
2078+
key_idx++;
2079+
}
2080+
dbfull()->TEST_WaitForCompact();
2081+
// Suppose each file flushed from mem table has size 1. Now we compact
2082+
// (level0_file_num_compaction_trigger+1)=4 files and should have a big
2083+
// file of size 4.
2084+
ASSERT_EQ(NumTableFilesAtLevel(0), 1);
2085+
for (int i = 1; i < options.num_levels ; i++) {
2086+
ASSERT_EQ(NumTableFilesAtLevel(i), 0);
2087+
}
2088+
2089+
// Stage 2:
2090+
// Now we have one file at level 0, with size 4. We also have some data in
2091+
// mem table. Let's continue generating new files at level 0, but don't
2092+
// trigger level-0 compaction.
2093+
// First, clean up memtable before inserting new data. This will generate
2094+
// a level-0 file, with size around 0.4 (according to previously written
2095+
// data amount).
2096+
dbfull()->Flush(FlushOptions());
2097+
for (int num = 0;
2098+
num < options.level0_file_num_compaction_trigger-3;
2099+
num++) {
2100+
// Write 120KB (12 values, each 10K)
2101+
for (int i = 0; i < 12; i++) {
2102+
ASSERT_OK(Put(Key(key_idx), RandomString(&rnd, 10000)));
2103+
key_idx++;
2104+
}
2105+
dbfull()->TEST_WaitForFlushMemTable();
2106+
ASSERT_EQ(NumTableFilesAtLevel(0), num + 3);
2107+
}
2108+
2109+
// Generate one more file at level-0, which should trigger level-0
2110+
// compaction.
2111+
for (int i = 0; i < 12; i++) {
2112+
ASSERT_OK(Put(Key(key_idx), RandomString(&rnd, 10000)));
2113+
key_idx++;
2114+
}
2115+
dbfull()->TEST_WaitForCompact();
2116+
// Before compaction, we have 4 files at level 0, with size 4, 0.4, 1, 1.
2117+
// After compaction, we should have 3 files, with size 4, 0.4, 2.
2118+
ASSERT_EQ(NumTableFilesAtLevel(0), 3);
2119+
for (int i = 1; i < options.num_levels ; i++) {
2120+
ASSERT_EQ(NumTableFilesAtLevel(i), 0);
2121+
}
2122+
2123+
// Stage 3:
2124+
// Now we have 3 files at level 0, with size 4, 0.4, 2. Generate one
2125+
// more file at level-0, which should trigger level-0 compaction.
2126+
for (int i = 0; i < 12; i++) {
2127+
ASSERT_OK(Put(Key(key_idx), RandomString(&rnd, 10000)));
2128+
key_idx++;
2129+
}
2130+
dbfull()->TEST_WaitForCompact();
2131+
// Level-0 compaction is triggered, but no file will be picked up.
2132+
ASSERT_EQ(NumTableFilesAtLevel(0), 4);
2133+
for (int i = 1; i < options.num_levels ; i++) {
2134+
ASSERT_EQ(NumTableFilesAtLevel(i), 0);
2135+
}
2136+
}
2137+
20462138
#if defined(SNAPPY) && defined(ZLIB) && defined(BZIP2)
20472139
TEST(DBTest, CompressedCache) {
20482140
int num_iter = 80;

0 commit comments

Comments
 (0)