compaction_picker_fifo.cc 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
  2. // This source code is licensed under both the GPLv2 (found in the
  3. // COPYING file in the root directory) and Apache 2.0 License
  4. // (found in the LICENSE.Apache file in the root directory).
  5. //
  6. // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
  7. // Use of this source code is governed by a BSD-style license that can be
  8. // found in the LICENSE file. See the AUTHORS file for names of contributors.
  9. #include "db/compaction/compaction_picker_fifo.h"
  10. #ifndef ROCKSDB_LITE
  11. #include <cinttypes>
  12. #include <string>
  13. #include <vector>
  14. #include "db/column_family.h"
  15. #include "logging/log_buffer.h"
  16. #include "util/string_util.h"
  17. namespace ROCKSDB_NAMESPACE {
  18. namespace {
  19. uint64_t GetTotalFilesSize(const std::vector<FileMetaData*>& files) {
  20. uint64_t total_size = 0;
  21. for (const auto& f : files) {
  22. total_size += f->fd.file_size;
  23. }
  24. return total_size;
  25. }
  26. } // anonymous namespace
  27. bool FIFOCompactionPicker::NeedsCompaction(
  28. const VersionStorageInfo* vstorage) const {
  29. const int kLevel0 = 0;
  30. return vstorage->CompactionScore(kLevel0) >= 1;
  31. }
  32. Compaction* FIFOCompactionPicker::PickTTLCompaction(
  33. const std::string& cf_name, const MutableCFOptions& mutable_cf_options,
  34. VersionStorageInfo* vstorage, LogBuffer* log_buffer) {
  35. assert(mutable_cf_options.ttl > 0);
  36. const int kLevel0 = 0;
  37. const std::vector<FileMetaData*>& level_files = vstorage->LevelFiles(kLevel0);
  38. uint64_t total_size = GetTotalFilesSize(level_files);
  39. int64_t _current_time;
  40. auto status = ioptions_.env->GetCurrentTime(&_current_time);
  41. if (!status.ok()) {
  42. ROCKS_LOG_BUFFER(log_buffer,
  43. "[%s] FIFO compaction: Couldn't get current time: %s. "
  44. "Not doing compactions based on TTL. ",
  45. cf_name.c_str(), status.ToString().c_str());
  46. return nullptr;
  47. }
  48. const uint64_t current_time = static_cast<uint64_t>(_current_time);
  49. if (!level0_compactions_in_progress_.empty()) {
  50. ROCKS_LOG_BUFFER(
  51. log_buffer,
  52. "[%s] FIFO compaction: Already executing compaction. No need "
  53. "to run parallel compactions since compactions are very fast",
  54. cf_name.c_str());
  55. return nullptr;
  56. }
  57. std::vector<CompactionInputFiles> inputs;
  58. inputs.emplace_back();
  59. inputs[0].level = 0;
  60. // avoid underflow
  61. if (current_time > mutable_cf_options.ttl) {
  62. for (auto ritr = level_files.rbegin(); ritr != level_files.rend(); ++ritr) {
  63. FileMetaData* f = *ritr;
  64. if (f->fd.table_reader && f->fd.table_reader->GetTableProperties()) {
  65. uint64_t creation_time =
  66. f->fd.table_reader->GetTableProperties()->creation_time;
  67. if (creation_time == 0 ||
  68. creation_time >= (current_time - mutable_cf_options.ttl)) {
  69. break;
  70. }
  71. total_size -= f->compensated_file_size;
  72. inputs[0].files.push_back(f);
  73. }
  74. }
  75. }
  76. // Return a nullptr and proceed to size-based FIFO compaction if:
  77. // 1. there are no files older than ttl OR
  78. // 2. there are a few files older than ttl, but deleting them will not bring
  79. // the total size to be less than max_table_files_size threshold.
  80. if (inputs[0].files.empty() ||
  81. total_size >
  82. mutable_cf_options.compaction_options_fifo.max_table_files_size) {
  83. return nullptr;
  84. }
  85. for (const auto& f : inputs[0].files) {
  86. uint64_t creation_time = 0;
  87. if (f && f->fd.table_reader && f->fd.table_reader->GetTableProperties()) {
  88. creation_time = f->fd.table_reader->GetTableProperties()->creation_time;
  89. }
  90. ROCKS_LOG_BUFFER(log_buffer,
  91. "[%s] FIFO compaction: picking file %" PRIu64
  92. " with creation time %" PRIu64 " for deletion",
  93. cf_name.c_str(), f->fd.GetNumber(), creation_time);
  94. }
  95. Compaction* c = new Compaction(
  96. vstorage, ioptions_, mutable_cf_options, std::move(inputs), 0, 0, 0, 0,
  97. kNoCompression, ioptions_.compression_opts, /* max_subcompactions */ 0,
  98. {}, /* is manual */ false, vstorage->CompactionScore(0),
  99. /* is deletion compaction */ true, CompactionReason::kFIFOTtl);
  100. return c;
  101. }
  102. Compaction* FIFOCompactionPicker::PickSizeCompaction(
  103. const std::string& cf_name, const MutableCFOptions& mutable_cf_options,
  104. VersionStorageInfo* vstorage, LogBuffer* log_buffer) {
  105. const int kLevel0 = 0;
  106. const std::vector<FileMetaData*>& level_files = vstorage->LevelFiles(kLevel0);
  107. uint64_t total_size = GetTotalFilesSize(level_files);
  108. if (total_size <=
  109. mutable_cf_options.compaction_options_fifo.max_table_files_size ||
  110. level_files.size() == 0) {
  111. // total size not exceeded
  112. if (mutable_cf_options.compaction_options_fifo.allow_compaction &&
  113. level_files.size() > 0) {
  114. CompactionInputFiles comp_inputs;
  115. // try to prevent same files from being compacted multiple times, which
  116. // could produce large files that may never TTL-expire. Achieve this by
  117. // disallowing compactions with files larger than memtable (inflate its
  118. // size by 10% to account for uncompressed L0 files that may have size
  119. // slightly greater than memtable size limit).
  120. size_t max_compact_bytes_per_del_file =
  121. static_cast<size_t>(MultiplyCheckOverflow(
  122. static_cast<uint64_t>(mutable_cf_options.write_buffer_size),
  123. 1.1));
  124. if (FindIntraL0Compaction(
  125. level_files,
  126. mutable_cf_options
  127. .level0_file_num_compaction_trigger /* min_files_to_compact */
  128. ,
  129. max_compact_bytes_per_del_file,
  130. mutable_cf_options.max_compaction_bytes, &comp_inputs)) {
  131. Compaction* c = new Compaction(
  132. vstorage, ioptions_, mutable_cf_options, {comp_inputs}, 0,
  133. 16 * 1024 * 1024 /* output file size limit */,
  134. 0 /* max compaction bytes, not applicable */,
  135. 0 /* output path ID */, mutable_cf_options.compression,
  136. ioptions_.compression_opts, 0 /* max_subcompactions */, {},
  137. /* is manual */ false, vstorage->CompactionScore(0),
  138. /* is deletion compaction */ false,
  139. CompactionReason::kFIFOReduceNumFiles);
  140. return c;
  141. }
  142. }
  143. ROCKS_LOG_BUFFER(
  144. log_buffer,
  145. "[%s] FIFO compaction: nothing to do. Total size %" PRIu64
  146. ", max size %" PRIu64 "\n",
  147. cf_name.c_str(), total_size,
  148. mutable_cf_options.compaction_options_fifo.max_table_files_size);
  149. return nullptr;
  150. }
  151. if (!level0_compactions_in_progress_.empty()) {
  152. ROCKS_LOG_BUFFER(
  153. log_buffer,
  154. "[%s] FIFO compaction: Already executing compaction. No need "
  155. "to run parallel compactions since compactions are very fast",
  156. cf_name.c_str());
  157. return nullptr;
  158. }
  159. std::vector<CompactionInputFiles> inputs;
  160. inputs.emplace_back();
  161. inputs[0].level = 0;
  162. for (auto ritr = level_files.rbegin(); ritr != level_files.rend(); ++ritr) {
  163. auto f = *ritr;
  164. total_size -= f->compensated_file_size;
  165. inputs[0].files.push_back(f);
  166. char tmp_fsize[16];
  167. AppendHumanBytes(f->fd.GetFileSize(), tmp_fsize, sizeof(tmp_fsize));
  168. ROCKS_LOG_BUFFER(log_buffer,
  169. "[%s] FIFO compaction: picking file %" PRIu64
  170. " with size %s for deletion",
  171. cf_name.c_str(), f->fd.GetNumber(), tmp_fsize);
  172. if (total_size <=
  173. mutable_cf_options.compaction_options_fifo.max_table_files_size) {
  174. break;
  175. }
  176. }
  177. Compaction* c = new Compaction(
  178. vstorage, ioptions_, mutable_cf_options, std::move(inputs), 0, 0, 0, 0,
  179. kNoCompression, ioptions_.compression_opts, /* max_subcompactions */ 0,
  180. {}, /* is manual */ false, vstorage->CompactionScore(0),
  181. /* is deletion compaction */ true, CompactionReason::kFIFOMaxSize);
  182. return c;
  183. }
  184. Compaction* FIFOCompactionPicker::PickCompaction(
  185. const std::string& cf_name, const MutableCFOptions& mutable_cf_options,
  186. VersionStorageInfo* vstorage, LogBuffer* log_buffer,
  187. SequenceNumber /*earliest_memtable_seqno*/) {
  188. assert(vstorage->num_levels() == 1);
  189. Compaction* c = nullptr;
  190. if (mutable_cf_options.ttl > 0) {
  191. c = PickTTLCompaction(cf_name, mutable_cf_options, vstorage, log_buffer);
  192. }
  193. if (c == nullptr) {
  194. c = PickSizeCompaction(cf_name, mutable_cf_options, vstorage, log_buffer);
  195. }
  196. RegisterCompaction(c);
  197. return c;
  198. }
  199. Compaction* FIFOCompactionPicker::CompactRange(
  200. const std::string& cf_name, const MutableCFOptions& mutable_cf_options,
  201. VersionStorageInfo* vstorage, int input_level, int output_level,
  202. const CompactRangeOptions& /*compact_range_options*/,
  203. const InternalKey* /*begin*/, const InternalKey* /*end*/,
  204. InternalKey** compaction_end, bool* /*manual_conflict*/,
  205. uint64_t /*max_file_num_to_ignore*/) {
  206. #ifdef NDEBUG
  207. (void)input_level;
  208. (void)output_level;
  209. #endif
  210. assert(input_level == 0);
  211. assert(output_level == 0);
  212. *compaction_end = nullptr;
  213. LogBuffer log_buffer(InfoLogLevel::INFO_LEVEL, ioptions_.info_log);
  214. Compaction* c =
  215. PickCompaction(cf_name, mutable_cf_options, vstorage, &log_buffer);
  216. log_buffer.FlushBufferToLog();
  217. return c;
  218. }
  219. } // namespace ROCKSDB_NAMESPACE
  220. #endif // !ROCKSDB_LITE