| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394 |
- // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
- // This source code is licensed under both the GPLv2 (found in the
- // COPYING file in the root directory) and Apache 2.0 License
- // (found in the LICENSE.Apache file in the root directory).
- //
- #pragma once
- #include <algorithm>
- #include "db/version_edit.h"
- namespace ROCKSDB_NAMESPACE {
- // We boost files that are closer to TTL limit. This boosting could be
- // through FileMetaData.compensated_file_size but this compensated size
- // is widely used as something similar to file size so dramatically boost
- // the value might cause unintended consequences.
- //
- // This boosting algorithm can go very fancy, but here we use a simple
- // formula which can satisify:
- // (1) Different levels are triggered slightly differently to avoid
- // too many cascading cases
- // (2) Files in the same level get boosting more when TTL gets closer.
- //
- // Don't do any boosting before TTL has past by half. This is to make
- // sure lower write amp for most of the case. And all levels should be
- // fully boosted when total TTL compaction threshold triggers.
- // Differientiate boosting ranges of each level by 1/2. This will make
- // range for each level exponentially increasing. We could do it by
- // having them to be equal, or go even fancier. We can adjust it after
- // we observe the behavior in production.
- // The threshold starting boosting:
- // +------------------------------------------------------------------ +
- // ^ ^ ^ ^ ^ ^
- // Age 0 ... | | second last level thresold
- // | |
- // | third last level
- // |
- // forth last level
- //
- // We arbitrarily set with 0 when a file is aged boost_age_start and
- // grow linearly. The ratio is arbitrarily set so that when the next level
- // starts to boost, the previous level's boosting amount is 16.
- class FileTtlBooster {
- public:
- FileTtlBooster(uint64_t current_time, uint64_t ttl, int num_non_empty_levels,
- int level)
- : current_time_(current_time) {
- if (ttl == 0 || level == 0 || level >= num_non_empty_levels - 1) {
- enabled_ = false;
- boost_age_start_ = 0;
- boost_step_ = 1;
- } else {
- enabled_ = true;
- uint64_t all_boost_start_age = ttl / 2;
- uint64_t all_boost_age_range = (ttl / 32) * 31 - all_boost_start_age;
- // TODO(cbi): more reasonable algorithm that gives different values
- // when num_non_empty_levels - level - 1 > 63.
- uint64_t boost_age_range =
- all_boost_age_range >> std::min(63, num_non_empty_levels - level - 1);
- boost_age_start_ = all_boost_start_age + boost_age_range;
- const uint64_t kBoostRatio = 16;
- // prevent 0 value to avoid divide 0 error.
- boost_step_ = std::max(boost_age_range / kBoostRatio, uint64_t{1});
- }
- }
- uint64_t GetBoostScore(FileMetaData* f) {
- if (!enabled_) {
- return 1;
- }
- uint64_t oldest_ancester_time = f->TryGetOldestAncesterTime();
- if (oldest_ancester_time >= current_time_) {
- return 1;
- }
- uint64_t age = current_time_ - oldest_ancester_time;
- if (age > boost_age_start_) {
- // Use integer just for convenience.
- // We could make all file_to_order double if we want.
- // Technically this can overflow if users override timing and
- // give a very high current time. Ignore the case for simplicity.
- // Boosting is addition to current value, so +1. This will effectively
- // make boosting to kick in after the first boost_step_ is reached.
- return (age - boost_age_start_) / boost_step_ + 1;
- }
- return 1;
- }
- private:
- bool enabled_;
- uint64_t current_time_;
- uint64_t boost_age_start_;
- uint64_t boost_step_;
- };
- } // namespace ROCKSDB_NAMESPACE
|