/src/rocksdb/db/compaction/file_pri.h
Line | Count | Source (jump to first uncovered line) |
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 | | |
7 | | #pragma once |
8 | | #include <algorithm> |
9 | | |
10 | | #include "db/version_edit.h" |
11 | | |
12 | | namespace ROCKSDB_NAMESPACE { |
13 | | // We boost files that are closer to TTL limit. This boosting could be |
14 | | // through FileMetaData.compensated_file_size but this compensated size |
15 | | // is widely used as something similar to file size so dramatically boost |
16 | | // the value might cause unintended consequences. |
17 | | // |
18 | | // This boosting algorithm can go very fancy, but here we use a simple |
19 | | // formula which can satisify: |
20 | | // (1) Different levels are triggered slightly differently to avoid |
21 | | // too many cascading cases |
22 | | // (2) Files in the same level get boosting more when TTL gets closer. |
23 | | // |
24 | | // Don't do any boosting before TTL has past by half. This is to make |
25 | | // sure lower write amp for most of the case. And all levels should be |
26 | | // fully boosted when total TTL compaction threshold triggers. |
27 | | // Differientiate boosting ranges of each level by 1/2. This will make |
28 | | // range for each level exponentially increasing. We could do it by |
29 | | // having them to be equal, or go even fancier. We can adjust it after |
30 | | // we observe the behavior in production. |
31 | | // The threshold starting boosting: |
32 | | // +------------------------------------------------------------------ + |
33 | | // ^ ^ ^ ^ ^ ^ |
34 | | // Age 0 ... | | second last level thresold |
35 | | // | | |
36 | | // | third last level |
37 | | // | |
38 | | // forth last level |
39 | | // |
40 | | // We arbitrarily set with 0 when a file is aged boost_age_start and |
41 | | // grow linearly. The ratio is arbitrarily set so that when the next level |
42 | | // starts to boost, the previous level's boosting amount is 16. |
43 | | class FileTtlBooster { |
44 | | public: |
45 | | FileTtlBooster(uint64_t current_time, uint64_t ttl, int num_non_empty_levels, |
46 | | int level) |
47 | 442k | : current_time_(current_time) { |
48 | 442k | if (ttl == 0 || level == 0 || level >= num_non_empty_levels - 1) { |
49 | 385k | enabled_ = false; |
50 | 385k | boost_age_start_ = 0; |
51 | 385k | boost_step_ = 1; |
52 | 385k | } else { |
53 | 56.5k | enabled_ = true; |
54 | 56.5k | uint64_t all_boost_start_age = ttl / 2; |
55 | 56.5k | uint64_t all_boost_age_range = (ttl / 32) * 31 - all_boost_start_age; |
56 | | // TODO(cbi): more reasonable algorithm that gives different values |
57 | | // when num_non_empty_levels - level - 1 > 63. |
58 | 56.5k | uint64_t boost_age_range = |
59 | 56.5k | all_boost_age_range >> std::min(63, num_non_empty_levels - level - 1); |
60 | 56.5k | boost_age_start_ = all_boost_start_age + boost_age_range; |
61 | 56.5k | const uint64_t kBoostRatio = 16; |
62 | | // prevent 0 value to avoid divide 0 error. |
63 | 56.5k | boost_step_ = std::max(boost_age_range / kBoostRatio, uint64_t{1}); |
64 | 56.5k | } |
65 | 442k | } |
66 | | |
67 | 30.5k | uint64_t GetBoostScore(FileMetaData* f) { |
68 | 30.5k | if (!enabled_) { |
69 | 30.5k | return 1; |
70 | 30.5k | } |
71 | 0 | uint64_t oldest_ancester_time = f->TryGetOldestAncesterTime(); |
72 | 0 | if (oldest_ancester_time >= current_time_) { |
73 | 0 | return 1; |
74 | 0 | } |
75 | 0 | uint64_t age = current_time_ - oldest_ancester_time; |
76 | 0 | if (age > boost_age_start_) { |
77 | | // Use integer just for convenience. |
78 | | // We could make all file_to_order double if we want. |
79 | | // Technically this can overflow if users override timing and |
80 | | // give a very high current time. Ignore the case for simplicity. |
81 | | // Boosting is addition to current value, so +1. This will effectively |
82 | | // make boosting to kick in after the first boost_step_ is reached. |
83 | 0 | return (age - boost_age_start_) / boost_step_ + 1; |
84 | 0 | } |
85 | 0 | return 1; |
86 | 0 | } |
87 | | |
88 | | private: |
89 | | bool enabled_; |
90 | | uint64_t current_time_; |
91 | | uint64_t boost_age_start_; |
92 | | uint64_t boost_step_; |
93 | | }; |
94 | | } // namespace ROCKSDB_NAMESPACE |