From 7413306d9461fb8fb6242b8448f6808e9f148b71 Mon Sep 17 00:00:00 2001 From: Igor Canadi Date: Fri, 15 May 2015 14:14:40 -0700 Subject: [PATCH] Take a chance on a random file when choosing compaction Summary: When trying to compact entire database with SuggestCompactRange(), we'll first try the left-most files. This is pretty bad, because: 1) the left part of LSM tree will be overly compacted, but right part will not be touched 2) First compaction will pick up the left-most file. Second compaction will try to pick up next left-most, but this will not be possible, because there's a big chance that second's file range on N+1 level is already being compacted. I observe both of those problems when running Mongo+RocksDB and trying to compact the DB to clean up tombstones. I'm unable to clean them up :( This diff adds a bit of randomness into choosing a file. First, it chooses a file at random and tries to compact that one. This should solve both problems specified here. Test Plan: make check Reviewers: yhchiang, rven, sdong Reviewed By: sdong Subscribers: dhruba, leveldb Differential Revision: https://reviews.facebook.net/D38379 --- db/compaction_picker.cc | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/db/compaction_picker.cc b/db/compaction_picker.cc index d32ceb0fa..ea5fb25f7 100644 --- a/db/compaction_picker.cc +++ b/db/compaction_picker.cc @@ -16,9 +16,12 @@ #include #include #include +#include + #include "db/column_family.h" #include "db/filename.h" #include "util/log_buffer.h" +#include "util/random.h" #include "util/statistics.h" #include "util/string_util.h" #include "util/sync_point.h" @@ -744,8 +747,8 @@ void LevelCompactionPicker::PickFilesMarkedForCompactionExperimental( return; } - for (auto& level_file : vstorage->FilesMarkedForCompaction()) { - // If it's being compaction it has nothing to do here. + auto continuation = [&](std::pair level_file) { + // If it's being compacted it has nothing to do here. // If this assert() fails that means that some function marked some // files as being_compacted, but didn't call ComputeCompactionScore() assert(!level_file.second->being_compacted); @@ -754,7 +757,21 @@ void LevelCompactionPicker::PickFilesMarkedForCompactionExperimental( inputs->files = {level_file.second}; inputs->level = *level; - if (ExpandWhileOverlapping(cf_name, vstorage, inputs)) { + return ExpandWhileOverlapping(cf_name, vstorage, inputs); + }; + + // take a chance on a random file first + Random64 rnd(/* seed */ reinterpret_cast(vstorage)); + size_t random_file_index = static_cast(rnd.Uniform( + static_cast(vstorage->FilesMarkedForCompaction().size()))); + + if (continuation(vstorage->FilesMarkedForCompaction()[random_file_index])) { + // found the compaction! + return; + } + + for (auto& level_file : vstorage->FilesMarkedForCompaction()) { + if (continuation(level_file)) { // found the compaction! return; }