/Users/deen/code/yugabyte-db/src/yb/rocksdb/db/compaction_picker_test.cc
Line | Count | Source |
1 | | // Copyright (c) 2011-present, Facebook, Inc. All rights reserved. |
2 | | // This source code is licensed under the BSD-style license found in the |
3 | | // LICENSE file in the root directory of this source tree. An additional grant |
4 | | // of patent rights can be found in the PATENTS file in the same directory. |
5 | | // |
6 | | // The following only applies to changes made to this file as part of YugaByte development. |
7 | | // |
8 | | // Portions Copyright (c) YugaByte, Inc. |
9 | | // |
10 | | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except |
11 | | // in compliance with the License. You may obtain a copy of the License at |
12 | | // |
13 | | // http://www.apache.org/licenses/LICENSE-2.0 |
14 | | // |
15 | | // Unless required by applicable law or agreed to in writing, software distributed under the License |
16 | | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
17 | | // or implied. See the License for the specific language governing permissions and limitations |
18 | | // under the License. |
19 | | // |
20 | | |
21 | | #include <limits> |
22 | | #include <string> |
23 | | #include <utility> |
24 | | |
25 | | #include <gtest/gtest.h> |
26 | | |
27 | | #include "yb/rocksdb/db/compaction_picker.h" |
28 | | #include "yb/rocksdb/db/version_set.h" |
29 | | #include "yb/rocksdb/env.h" |
30 | | |
31 | | #include "yb/util/size_literals.h" |
32 | | #include "yb/util/string_util.h" |
33 | | #include "yb/rocksdb/util/testutil.h" |
34 | | |
35 | | using namespace yb::size_literals; |
36 | | |
37 | | namespace rocksdb { |
38 | | |
39 | | class CountingLogger : public Logger { |
40 | | public: |
41 | | using Logger::Logv; |
42 | 21 | void Logv(const char* format, va_list ap) override { log_count++; } |
43 | | size_t log_count; |
44 | | }; |
45 | | |
46 | | class CompactionPickerTest : public RocksDBTest { |
47 | | public: |
48 | | const Comparator* ucmp_; |
49 | | InternalKeyComparatorPtr icmp_; |
50 | | Options options_; |
51 | | ImmutableCFOptions ioptions_; |
52 | | MutableCFOptions mutable_cf_options_; |
53 | | LevelCompactionPicker level_compaction_picker; |
54 | | std::string cf_name_; |
55 | | CountingLogger logger_; |
56 | | LogBuffer log_buffer_; |
57 | | uint32_t file_num_; |
58 | | CompactionOptionsFIFO fifo_options_; |
59 | | std::unique_ptr<VersionStorageInfo> vstorage_; |
60 | | std::vector<std::unique_ptr<FileMetaData>> files_; |
61 | | // does not own FileMetaData |
62 | | std::unordered_map<uint32_t, std::pair<FileMetaData*, int>> file_map_; |
63 | | // input files to compaction process. |
64 | | std::vector<CompactionInputFiles> input_files_; |
65 | | int compaction_level_start_; |
66 | | |
67 | | CompactionPickerTest() |
68 | | : ucmp_(BytewiseComparator()), |
69 | | icmp_(std::make_shared<InternalKeyComparator>(ucmp_)), |
70 | | ioptions_(options_), |
71 | | mutable_cf_options_(options_, ioptions_), |
72 | | level_compaction_picker(ioptions_, icmp_.get()), |
73 | | cf_name_("dummy"), |
74 | | log_buffer_(InfoLogLevel::INFO_LEVEL, &logger_), |
75 | | file_num_(1), |
76 | 31 | vstorage_(nullptr) { |
77 | 31 | fifo_options_.max_table_files_size = 1; |
78 | 31 | mutable_cf_options_.RefreshDerivedOptions(ioptions_); |
79 | 31 | ioptions_.db_paths.emplace_back("dummy", |
80 | 31 | std::numeric_limits<uint64_t>::max()); |
81 | 31 | } |
82 | | |
83 | 31 | ~CompactionPickerTest() { |
84 | 31 | log_buffer_.FlushBufferToLog(); |
85 | 31 | } |
86 | | |
87 | 164 | void NewVersionStorage(int num_levels, CompactionStyle style) { |
88 | 164 | DeleteVersionStorage(); |
89 | 164 | options_.num_levels = num_levels; |
90 | 164 | vstorage_.reset(new VersionStorageInfo( |
91 | 164 | icmp_, ucmp_, options_.num_levels, style, nullptr)); |
92 | 164 | vstorage_->CalculateBaseBytes(ioptions_, mutable_cf_options_); |
93 | 164 | } |
94 | | |
95 | 266 | void DeleteVersionStorage() { |
96 | 266 | vstorage_.reset(); |
97 | 266 | files_.clear(); |
98 | 266 | file_map_.clear(); |
99 | 266 | input_files_.clear(); |
100 | 266 | } |
101 | | |
102 | | void Add(int level, uint32_t file_number, const char* smallest, |
103 | | const char* largest, uint64_t file_size = 0, uint32_t path_id = 0, |
104 | | SequenceNumber smallest_seq = 100, |
105 | 1.30k | SequenceNumber largest_seq = 100) { |
106 | 1.30k | assert(level < vstorage_->num_levels()); |
107 | 1.30k | FileMetaData* f = new FileMetaData; |
108 | | // For large SST use 512 bytes as base file size, for files smaller than 512 bytes use half of |
109 | | // total size as a base file size. |
110 | | // Some compaction picker tests are using small files (<512 and even 1-3) bytes, so for these |
111 | | // files we split them into (file_size / 2) bytes base file and the rest goes to data file. |
112 | 1.16k | const uint64_t base_file_size = file_size > 512 ? 512 : (file_size / 2); |
113 | 1.30k | f->fd = FileDescriptor(file_number, path_id, file_size, base_file_size); |
114 | 1.30k | f->smallest = MakeFileBoundaryValues(smallest, smallest_seq, kTypeValue); |
115 | 1.30k | f->largest = MakeFileBoundaryValues(largest, largest_seq, kTypeValue); |
116 | 1.30k | f->compensated_file_size = file_size; |
117 | 1.30k | f->refs = 0; |
118 | 1.30k | vstorage_->AddFile(level, f); |
119 | 1.30k | files_.emplace_back(f); |
120 | 1.30k | file_map_.insert({file_number, {f, level}}); |
121 | 1.30k | } |
122 | | |
123 | 8 | void SetCompactionInputFilesLevels(int level_count, int start_level) { |
124 | 8 | input_files_.resize(level_count); |
125 | 22 | for (int i = 0; i < level_count; ++i) { |
126 | 14 | input_files_[i].level = start_level + i; |
127 | 14 | } |
128 | 8 | compaction_level_start_ = start_level; |
129 | 8 | } |
130 | | |
131 | 25 | void AddToCompactionFiles(uint32_t file_number) { |
132 | 25 | auto iter = file_map_.find(file_number); |
133 | 25 | assert(iter != file_map_.end()); |
134 | 25 | int level = iter->second.second; |
135 | 25 | assert(level < vstorage_->num_levels()); |
136 | 25 | input_files_[level - compaction_level_start_].files.emplace_back( |
137 | 25 | iter->second.first); |
138 | 25 | } |
139 | | |
140 | 158 | void UpdateVersionStorageInfo() { |
141 | 158 | vstorage_->CalculateBaseBytes(ioptions_, mutable_cf_options_); |
142 | 158 | vstorage_->UpdateFilesByCompactionPri(mutable_cf_options_); |
143 | 158 | vstorage_->UpdateNumNonEmptyLevels(); |
144 | 158 | vstorage_->GenerateFileIndexer(); |
145 | 158 | vstorage_->GenerateLevelFilesBrief(); |
146 | 158 | vstorage_->ComputeCompactionScore(mutable_cf_options_, fifo_options_); |
147 | 158 | vstorage_->GenerateLevel0NonOverlapping(); |
148 | 158 | vstorage_->SetFinalized(); |
149 | 158 | } |
150 | | }; |
151 | | |
152 | 1 | TEST_F(CompactionPickerTest, Empty) { |
153 | 1 | NewVersionStorage(6, kCompactionStyleLevel); |
154 | 1 | UpdateVersionStorageInfo(); |
155 | 1 | std::unique_ptr<Compaction> compaction(level_compaction_picker.PickCompaction( |
156 | 1 | cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_)); |
157 | 1 | ASSERT_TRUE(compaction.get() == nullptr); |
158 | 1 | } |
159 | | |
160 | 1 | TEST_F(CompactionPickerTest, Single) { |
161 | 1 | NewVersionStorage(6, kCompactionStyleLevel); |
162 | 1 | mutable_cf_options_.level0_file_num_compaction_trigger = 2; |
163 | 1 | Add(0, 1U, "p", "q"); |
164 | 1 | UpdateVersionStorageInfo(); |
165 | | |
166 | 1 | std::unique_ptr<Compaction> compaction(level_compaction_picker.PickCompaction( |
167 | 1 | cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_)); |
168 | 1 | ASSERT_TRUE(compaction.get() == nullptr); |
169 | 1 | } |
170 | | |
171 | 1 | TEST_F(CompactionPickerTest, Level0Trigger) { |
172 | 1 | NewVersionStorage(6, kCompactionStyleLevel); |
173 | 1 | mutable_cf_options_.level0_file_num_compaction_trigger = 2; |
174 | 1 | Add(0, 1U, "150", "200"); |
175 | 1 | Add(0, 2U, "200", "250"); |
176 | | |
177 | 1 | UpdateVersionStorageInfo(); |
178 | | |
179 | 1 | std::unique_ptr<Compaction> compaction(level_compaction_picker.PickCompaction( |
180 | 1 | cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_)); |
181 | 1 | ASSERT_TRUE(compaction.get() != nullptr); |
182 | 1 | ASSERT_EQ(2U, compaction->num_input_files(0)); |
183 | 1 | ASSERT_EQ(1U, compaction->input(0, 0)->fd.GetNumber()); |
184 | 1 | ASSERT_EQ(2U, compaction->input(0, 1)->fd.GetNumber()); |
185 | 1 | } |
186 | | |
187 | 1 | TEST_F(CompactionPickerTest, Level1Trigger) { |
188 | 1 | NewVersionStorage(6, kCompactionStyleLevel); |
189 | 1 | Add(1, 66U, "150", "200", 1000000000U); |
190 | 1 | UpdateVersionStorageInfo(); |
191 | | |
192 | 1 | std::unique_ptr<Compaction> compaction(level_compaction_picker.PickCompaction( |
193 | 1 | cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_)); |
194 | 1 | ASSERT_TRUE(compaction.get() != nullptr); |
195 | 1 | ASSERT_EQ(1U, compaction->num_input_files(0)); |
196 | 1 | ASSERT_EQ(66U, compaction->input(0, 0)->fd.GetNumber()); |
197 | 1 | } |
198 | | |
199 | 1 | TEST_F(CompactionPickerTest, Level1Trigger2) { |
200 | 1 | NewVersionStorage(6, kCompactionStyleLevel); |
201 | 1 | Add(1, 66U, "150", "200", 1000000001U); |
202 | 1 | Add(1, 88U, "201", "300", 1000000000U); |
203 | 1 | Add(2, 6U, "150", "179", 1000000000U); |
204 | 1 | Add(2, 7U, "180", "220", 1000000000U); |
205 | 1 | Add(2, 8U, "221", "300", 1000000000U); |
206 | 1 | UpdateVersionStorageInfo(); |
207 | | |
208 | 1 | std::unique_ptr<Compaction> compaction(level_compaction_picker.PickCompaction( |
209 | 1 | cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_)); |
210 | 1 | ASSERT_TRUE(compaction.get() != nullptr); |
211 | 1 | ASSERT_EQ(1U, compaction->num_input_files(0)); |
212 | 1 | ASSERT_EQ(2U, compaction->num_input_files(1)); |
213 | 1 | ASSERT_EQ(66U, compaction->input(0, 0)->fd.GetNumber()); |
214 | 1 | ASSERT_EQ(6U, compaction->input(1, 0)->fd.GetNumber()); |
215 | 1 | ASSERT_EQ(7U, compaction->input(1, 1)->fd.GetNumber()); |
216 | 1 | } |
217 | | |
218 | 1 | TEST_F(CompactionPickerTest, LevelMaxScore) { |
219 | 1 | NewVersionStorage(6, kCompactionStyleLevel); |
220 | 1 | mutable_cf_options_.target_file_size_base = 10000000; |
221 | 1 | mutable_cf_options_.target_file_size_multiplier = 10; |
222 | 1 | Add(0, 1U, "150", "200", 1000000000U); |
223 | | // Level 1 score 1.2 |
224 | 1 | Add(1, 66U, "150", "200", 6000000U); |
225 | 1 | Add(1, 88U, "201", "300", 6000000U); |
226 | | // Level 2 score 1.8. File 7 is the largest. Should be picked |
227 | 1 | Add(2, 6U, "150", "179", 60000000U); |
228 | 1 | Add(2, 7U, "180", "220", 60000001U); |
229 | 1 | Add(2, 8U, "221", "300", 60000000U); |
230 | | // Level 3 score slightly larger than 1 |
231 | 1 | Add(3, 26U, "150", "170", 260000000U); |
232 | 1 | Add(3, 27U, "171", "179", 260000000U); |
233 | 1 | Add(3, 28U, "191", "220", 260000000U); |
234 | 1 | Add(3, 29U, "221", "300", 260000000U); |
235 | 1 | UpdateVersionStorageInfo(); |
236 | | |
237 | 1 | std::unique_ptr<Compaction> compaction(level_compaction_picker.PickCompaction( |
238 | 1 | cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_)); |
239 | 1 | ASSERT_TRUE(compaction.get() != nullptr); |
240 | 1 | ASSERT_EQ(1U, compaction->num_input_files(0)); |
241 | 1 | ASSERT_EQ(7U, compaction->input(0, 0)->fd.GetNumber()); |
242 | 1 | } |
243 | | |
244 | 1 | TEST_F(CompactionPickerTest, NeedsCompactionLevel) { |
245 | 1 | const int kLevels = 6; |
246 | 1 | const int kFileCount = 20; |
247 | | |
248 | 6 | for (int level = 0; level < kLevels - 1; ++level) { |
249 | 5 | NewVersionStorage(kLevels, kCompactionStyleLevel); |
250 | 5 | uint64_t file_size = vstorage_->MaxBytesForLevel(level) * 2 / kFileCount; |
251 | 105 | for (int file_count = 1; file_count <= kFileCount; ++file_count) { |
252 | | // start a brand new version in each test. |
253 | 100 | NewVersionStorage(kLevels, kCompactionStyleLevel); |
254 | 1.15k | for (int i = 0; i < file_count; ++i) { |
255 | 1.05k | Add(level, i, ToString((i + 100) * 1000).c_str(), |
256 | 1.05k | ToString((i + 100) * 1000 + 999).c_str(), |
257 | 1.05k | file_size, 0, i * 100, i * 100 + 99); |
258 | 1.05k | } |
259 | 100 | UpdateVersionStorageInfo(); |
260 | 100 | ASSERT_EQ(vstorage_->CompactionScoreLevel(0), level); |
261 | 100 | ASSERT_EQ(level_compaction_picker.NeedsCompaction(vstorage_.get()), |
262 | 100 | vstorage_->CompactionScore(0) >= 1); |
263 | | // release the version storage |
264 | 100 | DeleteVersionStorage(); |
265 | 100 | } |
266 | 5 | } |
267 | 1 | } |
268 | | |
269 | 1 | TEST_F(CompactionPickerTest, Level0TriggerDynamic) { |
270 | 1 | int num_levels = ioptions_.num_levels; |
271 | 1 | ioptions_.level_compaction_dynamic_level_bytes = true; |
272 | 1 | mutable_cf_options_.level0_file_num_compaction_trigger = 2; |
273 | 1 | mutable_cf_options_.max_bytes_for_level_base = 200; |
274 | 1 | mutable_cf_options_.max_bytes_for_level_multiplier = 10; |
275 | 1 | NewVersionStorage(num_levels, kCompactionStyleLevel); |
276 | 1 | Add(0, 1U, "150", "200"); |
277 | 1 | Add(0, 2U, "200", "250"); |
278 | | |
279 | 1 | UpdateVersionStorageInfo(); |
280 | | |
281 | 1 | std::unique_ptr<Compaction> compaction(level_compaction_picker.PickCompaction( |
282 | 1 | cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_)); |
283 | 1 | ASSERT_TRUE(compaction.get() != nullptr); |
284 | 1 | ASSERT_EQ(2U, compaction->num_input_files(0)); |
285 | 1 | ASSERT_EQ(1U, compaction->input(0, 0)->fd.GetNumber()); |
286 | 1 | ASSERT_EQ(2U, compaction->input(0, 1)->fd.GetNumber()); |
287 | 1 | ASSERT_EQ(1, static_cast<int>(compaction->num_input_levels())); |
288 | 1 | ASSERT_EQ(num_levels - 1, compaction->output_level()); |
289 | 1 | } |
290 | | |
291 | 1 | TEST_F(CompactionPickerTest, Level0TriggerDynamic2) { |
292 | 1 | int num_levels = ioptions_.num_levels; |
293 | 1 | ioptions_.level_compaction_dynamic_level_bytes = true; |
294 | 1 | mutable_cf_options_.level0_file_num_compaction_trigger = 2; |
295 | 1 | mutable_cf_options_.max_bytes_for_level_base = 200; |
296 | 1 | mutable_cf_options_.max_bytes_for_level_multiplier = 10; |
297 | 1 | NewVersionStorage(num_levels, kCompactionStyleLevel); |
298 | 1 | Add(0, 1U, "150", "200"); |
299 | 1 | Add(0, 2U, "200", "250"); |
300 | 1 | Add(num_levels - 1, 3U, "200", "250", 300U); |
301 | | |
302 | 1 | UpdateVersionStorageInfo(); |
303 | 1 | ASSERT_EQ(vstorage_->base_level(), num_levels - 2); |
304 | | |
305 | 1 | std::unique_ptr<Compaction> compaction(level_compaction_picker.PickCompaction( |
306 | 1 | cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_)); |
307 | 1 | ASSERT_TRUE(compaction.get() != nullptr); |
308 | 1 | ASSERT_EQ(2U, compaction->num_input_files(0)); |
309 | 1 | ASSERT_EQ(1U, compaction->input(0, 0)->fd.GetNumber()); |
310 | 1 | ASSERT_EQ(2U, compaction->input(0, 1)->fd.GetNumber()); |
311 | 1 | ASSERT_EQ(1, static_cast<int>(compaction->num_input_levels())); |
312 | 1 | ASSERT_EQ(num_levels - 2, compaction->output_level()); |
313 | 1 | } |
314 | | |
315 | 1 | TEST_F(CompactionPickerTest, Level0TriggerDynamic3) { |
316 | 1 | int num_levels = ioptions_.num_levels; |
317 | 1 | ioptions_.level_compaction_dynamic_level_bytes = true; |
318 | 1 | mutable_cf_options_.level0_file_num_compaction_trigger = 2; |
319 | 1 | mutable_cf_options_.max_bytes_for_level_base = 200; |
320 | 1 | mutable_cf_options_.max_bytes_for_level_multiplier = 10; |
321 | 1 | NewVersionStorage(num_levels, kCompactionStyleLevel); |
322 | 1 | Add(0, 1U, "150", "200"); |
323 | 1 | Add(0, 2U, "200", "250"); |
324 | 1 | Add(num_levels - 1, 3U, "200", "250", 300U); |
325 | 1 | Add(num_levels - 1, 4U, "300", "350", 3000U); |
326 | | |
327 | 1 | UpdateVersionStorageInfo(); |
328 | 1 | ASSERT_EQ(vstorage_->base_level(), num_levels - 3); |
329 | | |
330 | 1 | std::unique_ptr<Compaction> compaction(level_compaction_picker.PickCompaction( |
331 | 1 | cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_)); |
332 | 1 | ASSERT_TRUE(compaction.get() != nullptr); |
333 | 1 | ASSERT_EQ(2U, compaction->num_input_files(0)); |
334 | 1 | ASSERT_EQ(1U, compaction->input(0, 0)->fd.GetNumber()); |
335 | 1 | ASSERT_EQ(2U, compaction->input(0, 1)->fd.GetNumber()); |
336 | 1 | ASSERT_EQ(1, static_cast<int>(compaction->num_input_levels())); |
337 | 1 | ASSERT_EQ(num_levels - 3, compaction->output_level()); |
338 | 1 | } |
339 | | |
340 | 1 | TEST_F(CompactionPickerTest, Level0TriggerDynamic4) { |
341 | 1 | int num_levels = ioptions_.num_levels; |
342 | 1 | ioptions_.level_compaction_dynamic_level_bytes = true; |
343 | 1 | mutable_cf_options_.level0_file_num_compaction_trigger = 2; |
344 | 1 | mutable_cf_options_.max_bytes_for_level_base = 200; |
345 | 1 | mutable_cf_options_.max_bytes_for_level_multiplier = 10; |
346 | 1 | NewVersionStorage(num_levels, kCompactionStyleLevel); |
347 | 1 | Add(0, 1U, "150", "200"); |
348 | 1 | Add(0, 2U, "200", "250"); |
349 | 1 | Add(num_levels - 1, 3U, "200", "250", 300U); |
350 | 1 | Add(num_levels - 1, 4U, "300", "350", 3000U); |
351 | 1 | Add(num_levels - 3, 5U, "150", "180", 3U); |
352 | 1 | Add(num_levels - 3, 6U, "181", "300", 3U); |
353 | 1 | Add(num_levels - 3, 7U, "400", "450", 3U); |
354 | | |
355 | 1 | UpdateVersionStorageInfo(); |
356 | 1 | ASSERT_EQ(vstorage_->base_level(), num_levels - 3); |
357 | | |
358 | 1 | std::unique_ptr<Compaction> compaction(level_compaction_picker.PickCompaction( |
359 | 1 | cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_)); |
360 | 1 | ASSERT_TRUE(compaction.get() != nullptr); |
361 | 1 | ASSERT_EQ(2U, compaction->num_input_files(0)); |
362 | 1 | ASSERT_EQ(1U, compaction->input(0, 0)->fd.GetNumber()); |
363 | 1 | ASSERT_EQ(2U, compaction->input(0, 1)->fd.GetNumber()); |
364 | 1 | ASSERT_EQ(2U, compaction->num_input_files(1)); |
365 | 1 | ASSERT_EQ(num_levels - 3, compaction->level(1)); |
366 | 1 | ASSERT_EQ(5U, compaction->input(1, 0)->fd.GetNumber()); |
367 | 1 | ASSERT_EQ(6U, compaction->input(1, 1)->fd.GetNumber()); |
368 | 1 | ASSERT_EQ(2, static_cast<int>(compaction->num_input_levels())); |
369 | 1 | ASSERT_EQ(num_levels - 3, compaction->output_level()); |
370 | 1 | } |
371 | | |
372 | 1 | TEST_F(CompactionPickerTest, LevelTriggerDynamic4) { |
373 | 1 | int num_levels = ioptions_.num_levels; |
374 | 1 | ioptions_.level_compaction_dynamic_level_bytes = true; |
375 | 1 | mutable_cf_options_.level0_file_num_compaction_trigger = 2; |
376 | 1 | mutable_cf_options_.max_bytes_for_level_base = 200; |
377 | 1 | mutable_cf_options_.max_bytes_for_level_multiplier = 10; |
378 | 1 | NewVersionStorage(num_levels, kCompactionStyleLevel); |
379 | 1 | Add(0, 1U, "150", "200"); |
380 | 1 | Add(num_levels - 1, 3U, "200", "250", 300U); |
381 | 1 | Add(num_levels - 1, 4U, "300", "350", 3000U); |
382 | 1 | Add(num_levels - 1, 4U, "400", "450", 3U); |
383 | 1 | Add(num_levels - 2, 5U, "150", "180", 300U); |
384 | 1 | Add(num_levels - 2, 6U, "181", "350", 500U); |
385 | 1 | Add(num_levels - 2, 7U, "400", "450", 200U); |
386 | | |
387 | 1 | UpdateVersionStorageInfo(); |
388 | | |
389 | 1 | std::unique_ptr<Compaction> compaction(level_compaction_picker.PickCompaction( |
390 | 1 | cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_)); |
391 | 1 | ASSERT_TRUE(compaction.get() != nullptr); |
392 | 1 | ASSERT_EQ(1U, compaction->num_input_files(0)); |
393 | 1 | ASSERT_EQ(6U, compaction->input(0, 0)->fd.GetNumber()); |
394 | 1 | ASSERT_EQ(2U, compaction->num_input_files(1)); |
395 | 1 | ASSERT_EQ(3U, compaction->input(1, 0)->fd.GetNumber()); |
396 | 1 | ASSERT_EQ(4U, compaction->input(1, 1)->fd.GetNumber()); |
397 | 1 | ASSERT_EQ(2U, compaction->num_input_levels()); |
398 | 1 | ASSERT_EQ(num_levels - 1, compaction->output_level()); |
399 | 1 | } |
400 | | |
401 | | // Universal and FIFO Compactions are not supported in ROCKSDB_LITE |
402 | | #ifndef ROCKSDB_LITE |
403 | 1 | TEST_F(CompactionPickerTest, NeedsCompactionUniversal) { |
404 | 1 | NewVersionStorage(1, kCompactionStyleUniversal); |
405 | 1 | UniversalCompactionPicker universal_compaction_picker( |
406 | 1 | ioptions_, icmp_.get()); |
407 | | // must return false when there's no files. |
408 | 1 | ASSERT_EQ(universal_compaction_picker.NeedsCompaction(vstorage_.get()), |
409 | 1 | false); |
410 | 1 | UpdateVersionStorageInfo(); |
411 | | |
412 | | // verify the trigger given different number of L0 files. |
413 | 1 | for (int i = 1; |
414 | 9 | i <= mutable_cf_options_.level0_file_num_compaction_trigger * 2; ++i) { |
415 | 8 | NewVersionStorage(1, kCompactionStyleUniversal); |
416 | 8 | Add(0, i, ToString((i + 100) * 1000).c_str(), |
417 | 8 | ToString((i + 100) * 1000 + 999).c_str(), 1000000, 0, i * 100, |
418 | 8 | i * 100 + 99); |
419 | 8 | UpdateVersionStorageInfo(); |
420 | 8 | ASSERT_EQ(level_compaction_picker.NeedsCompaction(vstorage_.get()), |
421 | 8 | vstorage_->CompactionScore(0) >= 1); |
422 | 8 | } |
423 | 1 | } |
424 | | |
425 | | // Tests if the correct compaction reason is used given which files are marked |
426 | | // as being compacted. Specifically, the test ensures that if the earliest file |
427 | | // available in a sequence of sorted runs is currently being compacted, it is |
428 | | // not included in the compaction. |
429 | 1 | TEST_F(CompactionPickerTest, CompactionUniversalPickForFilesBeingCompacted) { |
430 | 1 | NewVersionStorage(1, kCompactionStyleUniversal); |
431 | 1 | ioptions_.compaction_style = kCompactionStyleUniversal; |
432 | 1 | ioptions_.num_levels = 1; |
433 | 1 | mutable_cf_options_.write_buffer_size = 100_KB; |
434 | 1 | mutable_cf_options_.target_file_size_base = 32_KB; |
435 | 1 | mutable_cf_options_.level0_file_num_compaction_trigger = 3; |
436 | 1 | UniversalCompactionPicker universal_compaction_picker(ioptions_, icmp_.get()); |
437 | | // must return false when there's no files. |
438 | 1 | ASSERT_FALSE(universal_compaction_picker.NeedsCompaction(vstorage_.get())); |
439 | 1 | UpdateVersionStorageInfo(); |
440 | | |
441 | 1 | NewVersionStorage(1, kCompactionStyleUniversal); |
442 | | |
443 | | // Create three files, the earliest of which is significantly smaller than the other |
444 | | // two. This should cause the compaction picker to include all three files, |
445 | | // choosing "size amplification" as the compaction reason. |
446 | | // Add third file |
447 | 1 | Add(/* level = */ 0, /* file number = */ 3, /* smallest = */ "300000", |
448 | 1 | /* largest = */ "300999", /* file_size = */ 1000000, /* path_id = */ 0, |
449 | 1 | /* smallest seq num = */ 300, /* largest seq num = */ 399); |
450 | | // Add second file |
451 | 1 | Add(/* level = */ 0, /* file number = */ 2, /* smallest = */ "200000", |
452 | 1 | /* largest = */ "200999", /* file size = */ 1000000, /* path_id = */ 0, |
453 | 1 | /* smallest seq num = */ 200, /* largest seq num = */ 299); |
454 | | // Add first file |
455 | 1 | Add(/* level = */ 0, /* file number = */ 1, /* smallest = */ "100000", |
456 | 1 | /* largest = */ "100999", /* file size (smaller) = */ 10, |
457 | 1 | /* path_id = */ 0, /* smallest seq num = */ 100, /* largest seq num = */ 199); |
458 | | |
459 | 1 | UpdateVersionStorageInfo(); |
460 | 1 | auto compaction = universal_compaction_picker.PickCompaction( |
461 | 1 | cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_); |
462 | 1 | ASSERT_NE(compaction, nullptr); |
463 | 1 | ASSERT_EQ(compaction->compaction_reason(), CompactionReason::kUniversalSizeAmplification); |
464 | | // Verify that all three files are now being compacted. |
465 | 4 | for (int i = 1; i <= 3; i++) { |
466 | 3 | ASSERT_TRUE(file_map_.at(i).first->being_compacted); |
467 | 3 | } |
468 | | |
469 | | // Reset "being_compacted" on files 2 and 3 (simulates if earliest file is being compacted). |
470 | | // This scenario is particularly likely if file expiration based on TTL is enabled. |
471 | 1 | file_map_.at(2).first->being_compacted = false; |
472 | 1 | file_map_.at(3).first->being_compacted = false; |
473 | | |
474 | | // Files in sequence are [3 (available), 2 (available), 1 (being compacted)]. |
475 | | // The compaction picker should still create a compaction, but it will only include files |
476 | | // 3 and 2, and will be due to file ratio/sorted run num. |
477 | 1 | compaction = universal_compaction_picker.PickCompaction( |
478 | 1 | cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_); |
479 | 1 | ASSERT_NE(compaction, nullptr); |
480 | 1 | ASSERT_EQ(compaction->compaction_reason(), CompactionReason::kUniversalSortedRunNum); |
481 | | // Verify there are exactly 2 files being compacted. |
482 | 1 | ASSERT_EQ(compaction->inputs(0)->size(), 2); |
483 | 1 | } |
484 | | |
485 | | // Tests if the files can be trivially moved in multi level |
486 | | // universal compaction when allow_trivial_move option is set |
487 | | // In this test as the input files overlaps, they cannot |
488 | | // be trivially moved. |
489 | | |
490 | 1 | TEST_F(CompactionPickerTest, CannotTrivialMoveUniversal) { |
491 | 1 | const uint64_t kFileSize = 100000; |
492 | | |
493 | 1 | ioptions_.compaction_options_universal.allow_trivial_move = true; |
494 | 1 | NewVersionStorage(1, kCompactionStyleUniversal); |
495 | 1 | UniversalCompactionPicker universal_compaction_picker(ioptions_, icmp_.get()); |
496 | | // must return false when there's no files. |
497 | 1 | ASSERT_EQ(universal_compaction_picker.NeedsCompaction(vstorage_.get()), |
498 | 1 | false); |
499 | | |
500 | 1 | NewVersionStorage(3, kCompactionStyleUniversal); |
501 | | |
502 | 1 | Add(0, 1U, "150", "200", kFileSize, 0, 500, 550); |
503 | 1 | Add(0, 2U, "201", "250", kFileSize, 0, 401, 450); |
504 | 1 | Add(0, 4U, "260", "300", kFileSize, 0, 260, 300); |
505 | 1 | Add(1, 5U, "100", "151", kFileSize, 0, 200, 251); |
506 | 1 | Add(1, 3U, "301", "350", kFileSize, 0, 101, 150); |
507 | 1 | Add(2, 6U, "120", "200", kFileSize, 0, 20, 100); |
508 | | |
509 | 1 | UpdateVersionStorageInfo(); |
510 | | |
511 | 1 | std::unique_ptr<Compaction> compaction( |
512 | 1 | universal_compaction_picker.PickCompaction( |
513 | 1 | cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_)); |
514 | | |
515 | 1 | ASSERT_TRUE(!compaction->is_trivial_move()); |
516 | 1 | } |
517 | | // Tests if the files can be trivially moved in multi level |
518 | | // universal compaction when allow_trivial_move option is set |
519 | | // In this test as the input files doesn't overlaps, they should |
520 | | // be trivially moved. |
521 | 1 | TEST_F(CompactionPickerTest, AllowsTrivialMoveUniversal) { |
522 | 1 | const uint64_t kFileSize = 100000; |
523 | | |
524 | 1 | ioptions_.compaction_options_universal.allow_trivial_move = true; |
525 | 1 | UniversalCompactionPicker universal_compaction_picker(ioptions_, icmp_.get()); |
526 | | |
527 | 1 | NewVersionStorage(3, kCompactionStyleUniversal); |
528 | | |
529 | 1 | Add(0, 1U, "150", "200", kFileSize, 0, 500, 550); |
530 | 1 | Add(0, 2U, "201", "250", kFileSize, 0, 401, 450); |
531 | 1 | Add(0, 4U, "260", "300", kFileSize, 0, 260, 300); |
532 | 1 | Add(1, 5U, "010", "080", kFileSize, 0, 200, 251); |
533 | 1 | Add(2, 3U, "301", "350", kFileSize, 0, 101, 150); |
534 | | |
535 | 1 | UpdateVersionStorageInfo(); |
536 | | |
537 | 1 | std::unique_ptr<Compaction> compaction( |
538 | 1 | universal_compaction_picker.PickCompaction( |
539 | 1 | cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_)); |
540 | | |
541 | 1 | ASSERT_TRUE(compaction->is_trivial_move()); |
542 | 1 | } |
543 | | |
544 | 1 | TEST_F(CompactionPickerTest, NeedsCompactionFIFO) { |
545 | 1 | NewVersionStorage(1, kCompactionStyleFIFO); |
546 | 1 | const int kFileCount = |
547 | 1 | mutable_cf_options_.level0_file_num_compaction_trigger * 3; |
548 | 1 | const uint64_t kFileSize = 100000; |
549 | 1 | const uint64_t kMaxSize = kFileSize * kFileCount / 2; |
550 | | |
551 | 1 | fifo_options_.max_table_files_size = kMaxSize; |
552 | 1 | ioptions_.compaction_options_fifo = fifo_options_; |
553 | 1 | FIFOCompactionPicker fifo_compaction_picker(ioptions_, icmp_.get()); |
554 | | |
555 | 1 | UpdateVersionStorageInfo(); |
556 | | // must return false when there's no files. |
557 | 1 | ASSERT_EQ(fifo_compaction_picker.NeedsCompaction(vstorage_.get()), false); |
558 | | |
559 | | // verify whether compaction is needed based on the current |
560 | | // size of L0 files. |
561 | 1 | uint64_t current_size = 0; |
562 | 13 | for (int i = 1; i <= kFileCount; ++i) { |
563 | 12 | NewVersionStorage(1, kCompactionStyleFIFO); |
564 | 12 | Add(0, i, ToString((i + 100) * 1000).c_str(), |
565 | 12 | ToString((i + 100) * 1000 + 999).c_str(), |
566 | 12 | kFileSize, 0, i * 100, i * 100 + 99); |
567 | 12 | current_size += kFileSize; |
568 | 12 | UpdateVersionStorageInfo(); |
569 | 12 | ASSERT_EQ(level_compaction_picker.NeedsCompaction(vstorage_.get()), |
570 | 12 | vstorage_->CompactionScore(0) >= 1); |
571 | 12 | } |
572 | 1 | } |
573 | | #endif // ROCKSDB_LITE |
574 | | |
575 | 1 | TEST_F(CompactionPickerTest, CompactionPriMinOverlapping1) { |
576 | 1 | NewVersionStorage(6, kCompactionStyleLevel); |
577 | 1 | mutable_cf_options_.target_file_size_base = 10000000; |
578 | 1 | mutable_cf_options_.target_file_size_multiplier = 10; |
579 | 1 | mutable_cf_options_.compaction_pri = kMinOverlappingRatio; |
580 | | |
581 | 1 | Add(2, 6U, "150", "179", 50000000U); |
582 | 1 | Add(2, 7U, "180", "220", 50000000U); |
583 | 1 | Add(2, 8U, "321", "400", 50000000U); // File not overlapping |
584 | 1 | Add(2, 9U, "721", "800", 50000000U); |
585 | | |
586 | 1 | Add(3, 26U, "150", "170", 260000000U); |
587 | 1 | Add(3, 27U, "171", "179", 260000000U); |
588 | 1 | Add(3, 28U, "191", "220", 260000000U); |
589 | 1 | Add(3, 29U, "221", "300", 260000000U); |
590 | 1 | Add(3, 30U, "750", "900", 260000000U); |
591 | 1 | UpdateVersionStorageInfo(); |
592 | | |
593 | 1 | std::unique_ptr<Compaction> compaction(level_compaction_picker.PickCompaction( |
594 | 1 | cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_)); |
595 | 1 | ASSERT_TRUE(compaction.get() != nullptr); |
596 | 1 | ASSERT_EQ(1U, compaction->num_input_files(0)); |
597 | | // Pick file 8 because it overlaps with 0 files on level 3. |
598 | 1 | ASSERT_EQ(8U, compaction->input(0, 0)->fd.GetNumber()); |
599 | 1 | } |
600 | | |
601 | 1 | TEST_F(CompactionPickerTest, CompactionPriMinOverlapping2) { |
602 | 1 | NewVersionStorage(6, kCompactionStyleLevel); |
603 | 1 | mutable_cf_options_.target_file_size_base = 10000000; |
604 | 1 | mutable_cf_options_.target_file_size_multiplier = 10; |
605 | 1 | mutable_cf_options_.compaction_pri = kMinOverlappingRatio; |
606 | | |
607 | 1 | Add(2, 6U, "150", "175", |
608 | 1 | 60000000U); // Overlaps with file 26, 27, total size 521M |
609 | 1 | Add(2, 7U, "176", "200", 60000000U); // Overlaps with file 27, 28, total size |
610 | | // 520M, the smalelst overlapping |
611 | 1 | Add(2, 8U, "201", "300", |
612 | 1 | 60000000U); // Overlaps with file 28, 29, total size 521M |
613 | | |
614 | 1 | Add(3, 26U, "100", "110", 261000000U); |
615 | 1 | Add(3, 26U, "150", "170", 261000000U); |
616 | 1 | Add(3, 27U, "171", "179", 260000000U); |
617 | 1 | Add(3, 28U, "191", "220", 260000000U); |
618 | 1 | Add(3, 29U, "221", "300", 261000000U); |
619 | 1 | Add(3, 30U, "321", "400", 261000000U); |
620 | 1 | UpdateVersionStorageInfo(); |
621 | | |
622 | 1 | std::unique_ptr<Compaction> compaction(level_compaction_picker.PickCompaction( |
623 | 1 | cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_)); |
624 | 1 | ASSERT_TRUE(compaction.get() != nullptr); |
625 | 1 | ASSERT_EQ(1U, compaction->num_input_files(0)); |
626 | | // Picking file 7 because overlapping ratio is the biggest. |
627 | 1 | ASSERT_EQ(7U, compaction->input(0, 0)->fd.GetNumber()); |
628 | 1 | } |
629 | | |
630 | 1 | TEST_F(CompactionPickerTest, CompactionPriMinOverlapping3) { |
631 | 1 | NewVersionStorage(6, kCompactionStyleLevel); |
632 | 1 | mutable_cf_options_.target_file_size_base = 10000000; |
633 | 1 | mutable_cf_options_.target_file_size_multiplier = 10; |
634 | 1 | mutable_cf_options_.compaction_pri = kMinOverlappingRatio; |
635 | | |
636 | | // file 7 and 8 over lap with the same file, but file 8 is smaller so |
637 | | // it will be picked. |
638 | 1 | Add(2, 6U, "150", "175", 60000000U); // Overlaps with file 26, 27 |
639 | 1 | Add(2, 7U, "176", "200", 60000000U); // Overlaps with file 27 |
640 | 1 | Add(2, 8U, "201", "300", 61000000U); // Overlaps with file 27 |
641 | | |
642 | 1 | Add(3, 26U, "160", "165", 260000000U); |
643 | 1 | Add(3, 26U, "166", "170", 260000000U); |
644 | 1 | Add(3, 27U, "180", "400", 260000000U); |
645 | 1 | Add(3, 28U, "401", "500", 260000000U); |
646 | 1 | UpdateVersionStorageInfo(); |
647 | | |
648 | 1 | std::unique_ptr<Compaction> compaction(level_compaction_picker.PickCompaction( |
649 | 1 | cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_)); |
650 | 1 | ASSERT_TRUE(compaction.get() != nullptr); |
651 | 1 | ASSERT_EQ(1U, compaction->num_input_files(0)); |
652 | | // Picking file 8 because overlapping ratio is the biggest. |
653 | 1 | ASSERT_EQ(8U, compaction->input(0, 0)->fd.GetNumber()); |
654 | 1 | } |
655 | | |
656 | | // This test exhibits the bug where we don't properly reset parent_index in |
657 | | // PickCompaction() |
658 | 1 | TEST_F(CompactionPickerTest, ParentIndexResetBug) { |
659 | 1 | int num_levels = ioptions_.num_levels; |
660 | 1 | mutable_cf_options_.level0_file_num_compaction_trigger = 2; |
661 | 1 | mutable_cf_options_.max_bytes_for_level_base = 200; |
662 | 1 | NewVersionStorage(num_levels, kCompactionStyleLevel); |
663 | 1 | Add(0, 1U, "150", "200"); // <- marked for compaction |
664 | 1 | Add(1, 3U, "400", "500", 600); // <- this one needs compacting |
665 | 1 | Add(2, 4U, "150", "200"); |
666 | 1 | Add(2, 5U, "201", "210"); |
667 | 1 | Add(2, 6U, "300", "310"); |
668 | 1 | Add(2, 7U, "400", "500"); // <- being compacted |
669 | | |
670 | 1 | vstorage_->LevelFiles(2)[3]->being_compacted = true; |
671 | 1 | vstorage_->LevelFiles(0)[0]->marked_for_compaction = true; |
672 | | |
673 | 1 | UpdateVersionStorageInfo(); |
674 | | |
675 | 1 | std::unique_ptr<Compaction> compaction(level_compaction_picker.PickCompaction( |
676 | 1 | cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_)); |
677 | 1 | } |
678 | | |
679 | | // This test checks ExpandWhileOverlapping() by having overlapping user keys |
680 | | // ranges (with different sequence numbers) in the input files. |
681 | 1 | TEST_F(CompactionPickerTest, OverlappingUserKeys) { |
682 | 1 | NewVersionStorage(6, kCompactionStyleLevel); |
683 | 1 | Add(1, 1U, "100", "150", 1U); |
684 | | // Overlapping user keys |
685 | 1 | Add(1, 2U, "200", "400", 1U); |
686 | 1 | Add(1, 3U, "400", "500", 1000000000U, 0, 0); |
687 | 1 | Add(2, 4U, "600", "700", 1U); |
688 | 1 | UpdateVersionStorageInfo(); |
689 | | |
690 | 1 | std::unique_ptr<Compaction> compaction(level_compaction_picker.PickCompaction( |
691 | 1 | cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_)); |
692 | 1 | ASSERT_TRUE(compaction.get() != nullptr); |
693 | 1 | ASSERT_EQ(1U, compaction->num_input_levels()); |
694 | 1 | ASSERT_EQ(2U, compaction->num_input_files(0)); |
695 | 1 | ASSERT_EQ(2U, compaction->input(0, 0)->fd.GetNumber()); |
696 | 1 | ASSERT_EQ(3U, compaction->input(0, 1)->fd.GetNumber()); |
697 | 1 | } |
698 | | |
699 | 1 | TEST_F(CompactionPickerTest, OverlappingUserKeys2) { |
700 | 1 | NewVersionStorage(6, kCompactionStyleLevel); |
701 | | // Overlapping user keys on same level and output level |
702 | 1 | Add(1, 1U, "200", "400", 1000000000U); |
703 | 1 | Add(1, 2U, "400", "500", 1U, 0, 0); |
704 | 1 | Add(2, 3U, "400", "600", 1U); |
705 | | // The following file is not in the compaction despite overlapping user keys |
706 | 1 | Add(2, 4U, "600", "700", 1U, 0, 0); |
707 | 1 | UpdateVersionStorageInfo(); |
708 | | |
709 | 1 | std::unique_ptr<Compaction> compaction(level_compaction_picker.PickCompaction( |
710 | 1 | cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_)); |
711 | 1 | ASSERT_TRUE(compaction.get() != nullptr); |
712 | 1 | ASSERT_EQ(2U, compaction->num_input_levels()); |
713 | 1 | ASSERT_EQ(2U, compaction->num_input_files(0)); |
714 | 1 | ASSERT_EQ(1U, compaction->num_input_files(1)); |
715 | 1 | ASSERT_EQ(1U, compaction->input(0, 0)->fd.GetNumber()); |
716 | 1 | ASSERT_EQ(2U, compaction->input(0, 1)->fd.GetNumber()); |
717 | 1 | ASSERT_EQ(3U, compaction->input(1, 0)->fd.GetNumber()); |
718 | 1 | } |
719 | | |
720 | 1 | TEST_F(CompactionPickerTest, OverlappingUserKeys3) { |
721 | 1 | NewVersionStorage(6, kCompactionStyleLevel); |
722 | | // Chain of overlapping user key ranges (forces ExpandWhileOverlapping() to |
723 | | // expand multiple times) |
724 | 1 | Add(1, 1U, "100", "150", 1U); |
725 | 1 | Add(1, 2U, "150", "200", 1U, 0, 0); |
726 | 1 | Add(1, 3U, "200", "250", 1000000000U, 0, 0); |
727 | 1 | Add(1, 4U, "250", "300", 1U, 0, 0); |
728 | 1 | Add(1, 5U, "300", "350", 1U, 0, 0); |
729 | | // Output level overlaps with the beginning and the end of the chain |
730 | 1 | Add(2, 6U, "050", "100", 1U); |
731 | 1 | Add(2, 7U, "350", "400", 1U); |
732 | 1 | UpdateVersionStorageInfo(); |
733 | | |
734 | 1 | std::unique_ptr<Compaction> compaction(level_compaction_picker.PickCompaction( |
735 | 1 | cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_)); |
736 | 1 | ASSERT_TRUE(compaction.get() != nullptr); |
737 | 1 | ASSERT_EQ(2U, compaction->num_input_levels()); |
738 | 1 | ASSERT_EQ(5U, compaction->num_input_files(0)); |
739 | 1 | ASSERT_EQ(2U, compaction->num_input_files(1)); |
740 | 1 | ASSERT_EQ(1U, compaction->input(0, 0)->fd.GetNumber()); |
741 | 1 | ASSERT_EQ(2U, compaction->input(0, 1)->fd.GetNumber()); |
742 | 1 | ASSERT_EQ(3U, compaction->input(0, 2)->fd.GetNumber()); |
743 | 1 | ASSERT_EQ(4U, compaction->input(0, 3)->fd.GetNumber()); |
744 | 1 | ASSERT_EQ(5U, compaction->input(0, 4)->fd.GetNumber()); |
745 | 1 | ASSERT_EQ(6U, compaction->input(1, 0)->fd.GetNumber()); |
746 | 1 | ASSERT_EQ(7U, compaction->input(1, 1)->fd.GetNumber()); |
747 | 1 | } |
748 | | |
749 | 1 | TEST_F(CompactionPickerTest, NotScheduleL1IfL0WithHigherPri1) { |
750 | 1 | NewVersionStorage(6, kCompactionStyleLevel); |
751 | 1 | mutable_cf_options_.level0_file_num_compaction_trigger = 2; |
752 | 1 | mutable_cf_options_.max_bytes_for_level_base = 900000000U; |
753 | | |
754 | | // 6 L0 files, score 3. |
755 | 1 | Add(0, 1U, "000", "400", 1U); |
756 | 1 | Add(0, 2U, "001", "400", 1U, 0, 0); |
757 | 1 | Add(0, 3U, "001", "400", 1000000000U, 0, 0); |
758 | 1 | Add(0, 31U, "001", "400", 1000000000U, 0, 0); |
759 | 1 | Add(0, 32U, "001", "400", 1000000000U, 0, 0); |
760 | 1 | Add(0, 33U, "001", "400", 1000000000U, 0, 0); |
761 | | |
762 | | // L1 total size 2GB, score 2.2. If one file being comapcted, score 1.1. |
763 | 1 | Add(1, 4U, "050", "300", 1000000000U, 0, 0); |
764 | 1 | file_map_[4u].first->being_compacted = true; |
765 | 1 | Add(1, 5U, "301", "350", 1000000000U, 0, 0); |
766 | | |
767 | | // Output level overlaps with the beginning and the end of the chain |
768 | 1 | Add(2, 6U, "050", "100", 1U); |
769 | 1 | Add(2, 7U, "300", "400", 1U); |
770 | | |
771 | | // No compaction should be scheduled, if L0 has higher priority than L1 |
772 | | // but L0->L1 compaction is blocked by a file in L1 being compacted. |
773 | 1 | UpdateVersionStorageInfo(); |
774 | 1 | ASSERT_EQ(0, vstorage_->CompactionScoreLevel(0)); |
775 | 1 | ASSERT_EQ(1, vstorage_->CompactionScoreLevel(1)); |
776 | 1 | std::unique_ptr<Compaction> compaction(level_compaction_picker.PickCompaction( |
777 | 1 | cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_)); |
778 | 1 | ASSERT_TRUE(compaction.get() == nullptr); |
779 | 1 | } |
780 | | |
781 | 1 | TEST_F(CompactionPickerTest, NotScheduleL1IfL0WithHigherPri2) { |
782 | 1 | NewVersionStorage(6, kCompactionStyleLevel); |
783 | 1 | mutable_cf_options_.level0_file_num_compaction_trigger = 2; |
784 | 1 | mutable_cf_options_.max_bytes_for_level_base = 900000000U; |
785 | | |
786 | | // 6 L0 files, score 3. |
787 | 1 | Add(0, 1U, "000", "400", 1U); |
788 | 1 | Add(0, 2U, "001", "400", 1U, 0, 0); |
789 | 1 | Add(0, 3U, "001", "400", 1000000000U, 0, 0); |
790 | 1 | Add(0, 31U, "001", "400", 1000000000U, 0, 0); |
791 | 1 | Add(0, 32U, "001", "400", 1000000000U, 0, 0); |
792 | 1 | Add(0, 33U, "001", "400", 1000000000U, 0, 0); |
793 | | |
794 | | // L1 total size 2GB, score 2.2. If one file being comapcted, score 1.1. |
795 | 1 | Add(1, 4U, "050", "300", 1000000000U, 0, 0); |
796 | 1 | Add(1, 5U, "301", "350", 1000000000U, 0, 0); |
797 | | |
798 | | // Output level overlaps with the beginning and the end of the chain |
799 | 1 | Add(2, 6U, "050", "100", 1U); |
800 | 1 | Add(2, 7U, "300", "400", 1U); |
801 | | |
802 | | // If no file in L1 being compacted, L0->L1 compaction will be scheduled. |
803 | 1 | UpdateVersionStorageInfo(); // being_compacted flag is cleared here. |
804 | 1 | ASSERT_EQ(0, vstorage_->CompactionScoreLevel(0)); |
805 | 1 | ASSERT_EQ(1, vstorage_->CompactionScoreLevel(1)); |
806 | 1 | std::unique_ptr<Compaction> compaction(level_compaction_picker.PickCompaction( |
807 | 1 | cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_)); |
808 | 1 | ASSERT_TRUE(compaction.get() != nullptr); |
809 | 1 | } |
810 | | |
811 | 1 | TEST_F(CompactionPickerTest, NotScheduleL1IfL0WithHigherPri3) { |
812 | 1 | NewVersionStorage(6, kCompactionStyleLevel); |
813 | 1 | mutable_cf_options_.level0_file_num_compaction_trigger = 2; |
814 | 1 | mutable_cf_options_.max_bytes_for_level_base = 900000000U; |
815 | | |
816 | | // 6 L0 files, score 3. |
817 | 1 | Add(0, 1U, "000", "400", 1U); |
818 | 1 | Add(0, 2U, "001", "400", 1U, 0, 0); |
819 | 1 | Add(0, 3U, "001", "400", 1000000000U, 0, 0); |
820 | 1 | Add(0, 31U, "001", "400", 1000000000U, 0, 0); |
821 | 1 | Add(0, 32U, "001", "400", 1000000000U, 0, 0); |
822 | 1 | Add(0, 33U, "001", "400", 1000000000U, 0, 0); |
823 | | |
824 | | // L1 score more than 6. |
825 | 1 | Add(1, 4U, "050", "300", 1000000000U, 0, 0); |
826 | 1 | file_map_[4u].first->being_compacted = true; |
827 | 1 | Add(1, 5U, "301", "350", 1000000000U, 0, 0); |
828 | 1 | Add(1, 51U, "351", "400", 6000000000U, 0, 0); |
829 | | |
830 | | // Output level overlaps with the beginning and the end of the chain |
831 | 1 | Add(2, 6U, "050", "100", 1U); |
832 | 1 | Add(2, 7U, "300", "400", 1U); |
833 | | |
834 | | // If score in L1 is larger than L0, L1 compaction goes through despite |
835 | | // there is pending L0 compaction. |
836 | 1 | UpdateVersionStorageInfo(); |
837 | 1 | ASSERT_EQ(1, vstorage_->CompactionScoreLevel(0)); |
838 | 1 | ASSERT_EQ(0, vstorage_->CompactionScoreLevel(1)); |
839 | 1 | std::unique_ptr<Compaction> compaction(level_compaction_picker.PickCompaction( |
840 | 1 | cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_)); |
841 | 1 | ASSERT_TRUE(compaction.get() != nullptr); |
842 | 1 | } |
843 | | |
844 | 1 | TEST_F(CompactionPickerTest, EstimateCompactionBytesNeeded1) { |
845 | 1 | int num_levels = ioptions_.num_levels; |
846 | 1 | ioptions_.level_compaction_dynamic_level_bytes = false; |
847 | 1 | mutable_cf_options_.level0_file_num_compaction_trigger = 3; |
848 | 1 | mutable_cf_options_.max_bytes_for_level_base = 1000; |
849 | 1 | mutable_cf_options_.max_bytes_for_level_multiplier = 10; |
850 | 1 | NewVersionStorage(num_levels, kCompactionStyleLevel); |
851 | 1 | Add(0, 1U, "150", "200", 200); |
852 | 1 | Add(0, 2U, "150", "200", 200); |
853 | 1 | Add(0, 3U, "150", "200", 200); |
854 | | // Level 1 is over target by 200 |
855 | 1 | Add(1, 4U, "400", "500", 600); |
856 | 1 | Add(1, 5U, "600", "700", 600); |
857 | | // Level 2 is less than target 10000 even added size of level 1 |
858 | 1 | Add(2, 6U, "150", "200", 2500); |
859 | 1 | Add(2, 7U, "201", "210", 2000); |
860 | 1 | Add(2, 8U, "300", "310", 2500); |
861 | 1 | Add(2, 9U, "400", "500", 2500); |
862 | | // Level 3 exceeds target 100,000 of 1000 |
863 | 1 | Add(3, 10U, "400", "500", 101000); |
864 | | // Level 4 exceeds target 1,000,000 of 500 after adding size from level 3 |
865 | 1 | Add(4, 11U, "400", "500", 999500); |
866 | 1 | Add(5, 11U, "400", "500", 8000000); |
867 | | |
868 | 1 | UpdateVersionStorageInfo(); |
869 | | |
870 | 1 | ASSERT_EQ(2200u + 11000u + 5500u, |
871 | 1 | vstorage_->estimated_compaction_needed_bytes()); |
872 | 1 | } |
873 | | |
874 | 1 | TEST_F(CompactionPickerTest, EstimateCompactionBytesNeeded2) { |
875 | 1 | int num_levels = ioptions_.num_levels; |
876 | 1 | ioptions_.level_compaction_dynamic_level_bytes = false; |
877 | 1 | mutable_cf_options_.level0_file_num_compaction_trigger = 3; |
878 | 1 | mutable_cf_options_.max_bytes_for_level_base = 1000; |
879 | 1 | mutable_cf_options_.max_bytes_for_level_multiplier = 10; |
880 | 1 | NewVersionStorage(num_levels, kCompactionStyleLevel); |
881 | 1 | Add(0, 1U, "150", "200", 200); |
882 | 1 | Add(0, 2U, "150", "200", 200); |
883 | 1 | Add(0, 4U, "150", "200", 200); |
884 | 1 | Add(0, 5U, "150", "200", 200); |
885 | 1 | Add(0, 6U, "150", "200", 200); |
886 | | // Level 1 is over target by |
887 | 1 | Add(1, 7U, "400", "500", 200); |
888 | 1 | Add(1, 8U, "600", "700", 200); |
889 | | // Level 2 is less than target 10000 even added size of level 1 |
890 | 1 | Add(2, 9U, "150", "200", 9500); |
891 | 1 | Add(3, 10U, "400", "500", 101000); |
892 | | |
893 | 1 | UpdateVersionStorageInfo(); |
894 | | |
895 | 1 | ASSERT_EQ(1400u + 4400u + 11000u, |
896 | 1 | vstorage_->estimated_compaction_needed_bytes()); |
897 | 1 | } |
898 | | |
899 | 1 | TEST_F(CompactionPickerTest, EstimateCompactionBytesNeededDynamicLevel) { |
900 | 1 | int num_levels = ioptions_.num_levels; |
901 | 1 | ioptions_.level_compaction_dynamic_level_bytes = true; |
902 | 1 | mutable_cf_options_.level0_file_num_compaction_trigger = 3; |
903 | 1 | mutable_cf_options_.max_bytes_for_level_base = 1000; |
904 | 1 | mutable_cf_options_.max_bytes_for_level_multiplier = 10; |
905 | 1 | NewVersionStorage(num_levels, kCompactionStyleLevel); |
906 | | |
907 | | // Set Last level size 50000 |
908 | | // num_levels - 1 target 5000 |
909 | | // num_levels - 2 is base level with taret 500 |
910 | 1 | Add(num_levels - 1, 10U, "400", "500", 50000); |
911 | | |
912 | 1 | Add(0, 1U, "150", "200", 200); |
913 | 1 | Add(0, 2U, "150", "200", 200); |
914 | 1 | Add(0, 4U, "150", "200", 200); |
915 | 1 | Add(0, 5U, "150", "200", 200); |
916 | 1 | Add(0, 6U, "150", "200", 200); |
917 | | // num_levels - 3 is over target by 100 + 1000 |
918 | 1 | Add(num_levels - 3, 7U, "400", "500", 300); |
919 | 1 | Add(num_levels - 3, 8U, "600", "700", 300); |
920 | | // Level 2 is over target by 1100 + 100 |
921 | 1 | Add(num_levels - 2, 9U, "150", "200", 5100); |
922 | | |
923 | 1 | UpdateVersionStorageInfo(); |
924 | | |
925 | 1 | ASSERT_EQ(1600u + 12100u + 13200u, |
926 | 1 | vstorage_->estimated_compaction_needed_bytes()); |
927 | 1 | } |
928 | | |
929 | 1 | TEST_F(CompactionPickerTest, IsBottommostLevelTest) { |
930 | | // case 1: Higher levels are empty |
931 | 1 | NewVersionStorage(6, kCompactionStyleLevel); |
932 | 1 | Add(0, 1U, "a", "m"); |
933 | 1 | Add(0, 2U, "c", "z"); |
934 | 1 | Add(1, 3U, "d", "e"); |
935 | 1 | Add(1, 4U, "l", "p"); |
936 | 1 | Add(2, 5U, "g", "i"); |
937 | 1 | Add(2, 6U, "x", "z"); |
938 | 1 | UpdateVersionStorageInfo(); |
939 | 1 | SetCompactionInputFilesLevels(2, 1); |
940 | 1 | AddToCompactionFiles(3U); |
941 | 1 | AddToCompactionFiles(5U); |
942 | 1 | bool result = |
943 | 1 | Compaction::TEST_IsBottommostLevel(2, vstorage_.get(), input_files_); |
944 | 1 | ASSERT_TRUE(result); |
945 | | |
946 | | // case 2: Higher levels have no overlap |
947 | 1 | NewVersionStorage(6, kCompactionStyleLevel); |
948 | 1 | Add(0, 1U, "a", "m"); |
949 | 1 | Add(0, 2U, "c", "z"); |
950 | 1 | Add(1, 3U, "d", "e"); |
951 | 1 | Add(1, 4U, "l", "p"); |
952 | 1 | Add(2, 5U, "g", "i"); |
953 | 1 | Add(2, 6U, "x", "z"); |
954 | 1 | Add(3, 7U, "k", "p"); |
955 | 1 | Add(3, 8U, "t", "w"); |
956 | 1 | Add(4, 9U, "a", "b"); |
957 | 1 | Add(5, 10U, "c", "cc"); |
958 | 1 | UpdateVersionStorageInfo(); |
959 | 1 | SetCompactionInputFilesLevels(2, 1); |
960 | 1 | AddToCompactionFiles(3U); |
961 | 1 | AddToCompactionFiles(5U); |
962 | 1 | result = Compaction::TEST_IsBottommostLevel(2, vstorage_.get(), input_files_); |
963 | 1 | ASSERT_TRUE(result); |
964 | | |
965 | | // case 3.1: Higher levels (level 3) have overlap |
966 | 1 | NewVersionStorage(6, kCompactionStyleLevel); |
967 | 1 | Add(0, 1U, "a", "m"); |
968 | 1 | Add(0, 2U, "c", "z"); |
969 | 1 | Add(1, 3U, "d", "e"); |
970 | 1 | Add(1, 4U, "l", "p"); |
971 | 1 | Add(2, 5U, "g", "i"); |
972 | 1 | Add(2, 6U, "x", "z"); |
973 | 1 | Add(3, 7U, "e", "g"); |
974 | 1 | Add(3, 8U, "h", "k"); |
975 | 1 | Add(4, 9U, "a", "b"); |
976 | 1 | Add(5, 10U, "c", "cc"); |
977 | 1 | UpdateVersionStorageInfo(); |
978 | 1 | SetCompactionInputFilesLevels(2, 1); |
979 | 1 | AddToCompactionFiles(3U); |
980 | 1 | AddToCompactionFiles(5U); |
981 | 1 | result = Compaction::TEST_IsBottommostLevel(2, vstorage_.get(), input_files_); |
982 | 1 | ASSERT_FALSE(result); |
983 | | |
984 | | // case 3.2: Higher levels (level 5) have overlap |
985 | 1 | DeleteVersionStorage(); |
986 | 1 | NewVersionStorage(6, kCompactionStyleLevel); |
987 | 1 | Add(0, 1U, "a", "m"); |
988 | 1 | Add(0, 2U, "c", "z"); |
989 | 1 | Add(1, 3U, "d", "e"); |
990 | 1 | Add(1, 4U, "l", "p"); |
991 | 1 | Add(2, 5U, "g", "i"); |
992 | 1 | Add(2, 6U, "x", "z"); |
993 | 1 | Add(3, 7U, "j", "k"); |
994 | 1 | Add(3, 8U, "l", "m"); |
995 | 1 | Add(4, 9U, "a", "b"); |
996 | 1 | Add(5, 10U, "c", "cc"); |
997 | 1 | Add(5, 11U, "h", "k"); |
998 | 1 | Add(5, 12U, "y", "yy"); |
999 | 1 | Add(5, 13U, "z", "zz"); |
1000 | 1 | UpdateVersionStorageInfo(); |
1001 | 1 | SetCompactionInputFilesLevels(2, 1); |
1002 | 1 | AddToCompactionFiles(3U); |
1003 | 1 | AddToCompactionFiles(5U); |
1004 | 1 | result = Compaction::TEST_IsBottommostLevel(2, vstorage_.get(), input_files_); |
1005 | 1 | ASSERT_FALSE(result); |
1006 | | |
1007 | | // case 3.3: Higher levels (level 5) have overlap, but it's only overlapping |
1008 | | // one key ("d") |
1009 | 1 | NewVersionStorage(6, kCompactionStyleLevel); |
1010 | 1 | Add(0, 1U, "a", "m"); |
1011 | 1 | Add(0, 2U, "c", "z"); |
1012 | 1 | Add(1, 3U, "d", "e"); |
1013 | 1 | Add(1, 4U, "l", "p"); |
1014 | 1 | Add(2, 5U, "g", "i"); |
1015 | 1 | Add(2, 6U, "x", "z"); |
1016 | 1 | Add(3, 7U, "j", "k"); |
1017 | 1 | Add(3, 8U, "l", "m"); |
1018 | 1 | Add(4, 9U, "a", "b"); |
1019 | 1 | Add(5, 10U, "c", "cc"); |
1020 | 1 | Add(5, 11U, "ccc", "d"); |
1021 | 1 | Add(5, 12U, "y", "yy"); |
1022 | 1 | Add(5, 13U, "z", "zz"); |
1023 | 1 | UpdateVersionStorageInfo(); |
1024 | 1 | SetCompactionInputFilesLevels(2, 1); |
1025 | 1 | AddToCompactionFiles(3U); |
1026 | 1 | AddToCompactionFiles(5U); |
1027 | 1 | result = Compaction::TEST_IsBottommostLevel(2, vstorage_.get(), input_files_); |
1028 | 1 | ASSERT_FALSE(result); |
1029 | | |
1030 | | // Level 0 files overlap |
1031 | 1 | NewVersionStorage(6, kCompactionStyleLevel); |
1032 | 1 | Add(0, 1U, "s", "t"); |
1033 | 1 | Add(0, 2U, "a", "m"); |
1034 | 1 | Add(0, 3U, "b", "z"); |
1035 | 1 | Add(0, 4U, "e", "f"); |
1036 | 1 | Add(5, 10U, "y", "z"); |
1037 | 1 | UpdateVersionStorageInfo(); |
1038 | 1 | SetCompactionInputFilesLevels(1, 0); |
1039 | 1 | AddToCompactionFiles(1U); |
1040 | 1 | AddToCompactionFiles(2U); |
1041 | 1 | AddToCompactionFiles(3U); |
1042 | 1 | AddToCompactionFiles(4U); |
1043 | 1 | result = Compaction::TEST_IsBottommostLevel(2, vstorage_.get(), input_files_); |
1044 | 1 | ASSERT_FALSE(result); |
1045 | | |
1046 | | // Level 0 files don't overlap |
1047 | 1 | NewVersionStorage(6, kCompactionStyleLevel); |
1048 | 1 | Add(0, 1U, "s", "t"); |
1049 | 1 | Add(0, 2U, "a", "m"); |
1050 | 1 | Add(0, 3U, "b", "k"); |
1051 | 1 | Add(0, 4U, "e", "f"); |
1052 | 1 | Add(5, 10U, "y", "z"); |
1053 | 1 | UpdateVersionStorageInfo(); |
1054 | 1 | SetCompactionInputFilesLevels(1, 0); |
1055 | 1 | AddToCompactionFiles(1U); |
1056 | 1 | AddToCompactionFiles(2U); |
1057 | 1 | AddToCompactionFiles(3U); |
1058 | 1 | AddToCompactionFiles(4U); |
1059 | 1 | result = Compaction::TEST_IsBottommostLevel(2, vstorage_.get(), input_files_); |
1060 | 1 | ASSERT_TRUE(result); |
1061 | | |
1062 | | // Level 1 files overlap |
1063 | 1 | NewVersionStorage(6, kCompactionStyleLevel); |
1064 | 1 | Add(0, 1U, "s", "t"); |
1065 | 1 | Add(0, 2U, "a", "m"); |
1066 | 1 | Add(0, 3U, "b", "k"); |
1067 | 1 | Add(0, 4U, "e", "f"); |
1068 | 1 | Add(1, 5U, "a", "m"); |
1069 | 1 | Add(1, 6U, "n", "o"); |
1070 | 1 | Add(1, 7U, "w", "y"); |
1071 | 1 | Add(5, 10U, "y", "z"); |
1072 | 1 | UpdateVersionStorageInfo(); |
1073 | 1 | SetCompactionInputFilesLevels(2, 0); |
1074 | 1 | AddToCompactionFiles(1U); |
1075 | 1 | AddToCompactionFiles(2U); |
1076 | 1 | AddToCompactionFiles(3U); |
1077 | 1 | AddToCompactionFiles(4U); |
1078 | 1 | AddToCompactionFiles(5U); |
1079 | 1 | AddToCompactionFiles(6U); |
1080 | 1 | AddToCompactionFiles(7U); |
1081 | 1 | result = Compaction::TEST_IsBottommostLevel(2, vstorage_.get(), input_files_); |
1082 | 1 | ASSERT_FALSE(result); |
1083 | | |
1084 | 1 | DeleteVersionStorage(); |
1085 | 1 | } |
1086 | | |
1087 | | } // namespace rocksdb |
1088 | | |
1089 | 13.2k | int main(int argc, char** argv) { |
1090 | 13.2k | ::testing::InitGoogleTest(&argc, argv); |
1091 | 13.2k | return RUN_ALL_TESTS(); |
1092 | 13.2k | } |