]>
Commit | Line | Data |
---|---|---|
7c673cae | 1 | // Copyright (c) 2011-present, Facebook, Inc. All rights reserved. |
11fdf7f2 TL |
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). | |
7c673cae FG |
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 | ||
10 | #pragma once | |
11 | ||
12 | #include "rocksdb/env.h" | |
13 | #include "rocksdb/statistics.h" | |
14 | ||
15 | namespace rocksdb { | |
16 | ||
17 | class RateLimiter { | |
18 | public: | |
11fdf7f2 TL |
19 | enum class OpType { |
20 | // Limitation: we currently only invoke Request() with OpType::kRead for | |
21 | // compactions when DBOptions::new_table_reader_for_compaction_inputs is set | |
22 | kRead, | |
23 | kWrite, | |
24 | }; | |
25 | enum class Mode { | |
26 | kReadsOnly, | |
27 | kWritesOnly, | |
28 | kAllIo, | |
29 | }; | |
30 | ||
31 | // For API compatibility, default to rate-limiting writes only. | |
32 | explicit RateLimiter(Mode mode = Mode::kWritesOnly) : mode_(mode) {} | |
33 | ||
7c673cae FG |
34 | virtual ~RateLimiter() {} |
35 | ||
36 | // This API allows user to dynamically change rate limiter's bytes per second. | |
37 | // REQUIRED: bytes_per_second > 0 | |
38 | virtual void SetBytesPerSecond(int64_t bytes_per_second) = 0; | |
39 | ||
11fdf7f2 TL |
40 | // Deprecated. New RateLimiter derived classes should override |
41 | // Request(const int64_t, const Env::IOPriority, Statistics*) or | |
42 | // Request(const int64_t, const Env::IOPriority, Statistics*, OpType) | |
43 | // instead. | |
44 | // | |
45 | // Request for token for bytes. If this request can not be satisfied, the call | |
46 | // is blocked. Caller is responsible to make sure | |
7c673cae | 47 | // bytes <= GetSingleBurstBytes() |
11fdf7f2 | 48 | virtual void Request(const int64_t /*bytes*/, const Env::IOPriority /*pri*/) { |
7c673cae FG |
49 | assert(false); |
50 | } | |
51 | ||
11fdf7f2 | 52 | // Request for token for bytes and potentially update statistics. If this |
7c673cae FG |
53 | // request can not be satisfied, the call is blocked. Caller is responsible to |
54 | // make sure bytes <= GetSingleBurstBytes(). | |
55 | virtual void Request(const int64_t bytes, const Env::IOPriority pri, | |
56 | Statistics* /* stats */) { | |
57 | // For API compatibility, default implementation calls the older API in | |
58 | // which statistics are unsupported. | |
59 | Request(bytes, pri); | |
60 | } | |
61 | ||
11fdf7f2 TL |
62 | // Requests token to read or write bytes and potentially updates statistics. |
63 | // | |
64 | // If this request can not be satisfied, the call is blocked. Caller is | |
65 | // responsible to make sure bytes <= GetSingleBurstBytes(). | |
66 | virtual void Request(const int64_t bytes, const Env::IOPriority pri, | |
67 | Statistics* stats, OpType op_type) { | |
68 | if (IsRateLimited(op_type)) { | |
69 | Request(bytes, pri, stats); | |
70 | } | |
71 | } | |
72 | ||
73 | // Requests token to read or write bytes and potentially updates statistics. | |
74 | // Takes into account GetSingleBurstBytes() and alignment (e.g., in case of | |
75 | // direct I/O) to allocate an appropriate number of bytes, which may be less | |
76 | // than the number of bytes requested. | |
77 | virtual size_t RequestToken(size_t bytes, size_t alignment, | |
78 | Env::IOPriority io_priority, Statistics* stats, | |
79 | RateLimiter::OpType op_type); | |
80 | ||
7c673cae FG |
81 | // Max bytes can be granted in a single burst |
82 | virtual int64_t GetSingleBurstBytes() const = 0; | |
83 | ||
494da23a | 84 | // Total bytes that go through rate limiter |
7c673cae FG |
85 | virtual int64_t GetTotalBytesThrough( |
86 | const Env::IOPriority pri = Env::IO_TOTAL) const = 0; | |
87 | ||
494da23a | 88 | // Total # of requests that go through rate limiter |
7c673cae FG |
89 | virtual int64_t GetTotalRequests( |
90 | const Env::IOPriority pri = Env::IO_TOTAL) const = 0; | |
11fdf7f2 TL |
91 | |
92 | virtual int64_t GetBytesPerSecond() const = 0; | |
93 | ||
94 | virtual bool IsRateLimited(OpType op_type) { | |
95 | if ((mode_ == RateLimiter::Mode::kWritesOnly && | |
96 | op_type == RateLimiter::OpType::kRead) || | |
97 | (mode_ == RateLimiter::Mode::kReadsOnly && | |
98 | op_type == RateLimiter::OpType::kWrite)) { | |
99 | return false; | |
100 | } | |
101 | return true; | |
102 | } | |
103 | ||
104 | protected: | |
105 | Mode GetMode() { return mode_; } | |
106 | ||
107 | private: | |
108 | const Mode mode_; | |
7c673cae FG |
109 | }; |
110 | ||
111 | // Create a RateLimiter object, which can be shared among RocksDB instances to | |
112 | // control write rate of flush and compaction. | |
113 | // @rate_bytes_per_sec: this is the only parameter you want to set most of the | |
114 | // time. It controls the total write rate of compaction and flush in bytes per | |
115 | // second. Currently, RocksDB does not enforce rate limit for anything other | |
116 | // than flush and compaction, e.g. write to WAL. | |
117 | // @refill_period_us: this controls how often tokens are refilled. For example, | |
118 | // when rate_bytes_per_sec is set to 10MB/s and refill_period_us is set to | |
119 | // 100ms, then 1MB is refilled every 100ms internally. Larger value can lead to | |
120 | // burstier writes while smaller value introduces more CPU overhead. | |
121 | // The default should work for most cases. | |
122 | // @fairness: RateLimiter accepts high-pri requests and low-pri requests. | |
123 | // A low-pri request is usually blocked in favor of hi-pri request. Currently, | |
11fdf7f2 | 124 | // RocksDB assigns low-pri to request from compaction and high-pri to request |
7c673cae | 125 | // from flush. Low-pri requests can get blocked if flush requests come in |
11fdf7f2 | 126 | // continuously. This fairness parameter grants low-pri requests permission by |
7c673cae FG |
127 | // 1/fairness chance even though high-pri requests exist to avoid starvation. |
128 | // You should be good by leaving it at default 10. | |
11fdf7f2 TL |
129 | // @mode: Mode indicates which types of operations count against the limit. |
130 | // @auto_tuned: Enables dynamic adjustment of rate limit within the range | |
131 | // `[rate_bytes_per_sec / 20, rate_bytes_per_sec]`, according to | |
132 | // the recent demand for background I/O. | |
7c673cae | 133 | extern RateLimiter* NewGenericRateLimiter( |
11fdf7f2 TL |
134 | int64_t rate_bytes_per_sec, int64_t refill_period_us = 100 * 1000, |
135 | int32_t fairness = 10, | |
136 | RateLimiter::Mode mode = RateLimiter::Mode::kWritesOnly, | |
137 | bool auto_tuned = false); | |
7c673cae FG |
138 | |
139 | } // namespace rocksdb |