1 // Copyright (c) 2015, 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 package org.rocksdb;
7 
8 /**
9  * RateLimiter, which is used to control write rate of flush and
10  * compaction.
11  *
12  * @since 3.10.0
13  */
14 public class RateLimiter extends RocksObject {
15   public static final long DEFAULT_REFILL_PERIOD_MICROS = 100 * 1000;
16   public static final int DEFAULT_FAIRNESS = 10;
17   public static final RateLimiterMode DEFAULT_MODE =
18       RateLimiterMode.WRITES_ONLY;
19   public static final boolean DEFAULT_AUTOTUNE = false;
20 
21   /**
22    * RateLimiter constructor
23    *
24    * @param rateBytesPerSecond this is the only parameter you want to set
25    *     most of the time. It controls the total write rate of compaction
26    *     and flush in bytes per second. Currently, RocksDB does not enforce
27    *     rate limit for anything other than flush and compaction, e.g. write to
28    *     WAL.
29    */
RateLimiter(final long rateBytesPerSecond)30   public RateLimiter(final long rateBytesPerSecond) {
31     this(rateBytesPerSecond, DEFAULT_REFILL_PERIOD_MICROS, DEFAULT_FAIRNESS,
32         DEFAULT_MODE, DEFAULT_AUTOTUNE);
33   }
34 
35   /**
36    * RateLimiter constructor
37    *
38    * @param rateBytesPerSecond this is the only parameter you want to set
39    *     most of the time. It controls the total write rate of compaction
40    *     and flush in bytes per second. Currently, RocksDB does not enforce
41    *     rate limit for anything other than flush and compaction, e.g. write to
42    *     WAL.
43    * @param refillPeriodMicros this controls how often tokens are refilled. For
44    *     example,
45    *     when rate_bytes_per_sec is set to 10MB/s and refill_period_us is set to
46    *     100ms, then 1MB is refilled every 100ms internally. Larger value can
47    *     lead to burstier writes while smaller value introduces more CPU
48    *     overhead. The default of 100,000ms should work for most cases.
49    */
RateLimiter(final long rateBytesPerSecond, final long refillPeriodMicros)50   public RateLimiter(final long rateBytesPerSecond,
51       final long refillPeriodMicros) {
52     this(rateBytesPerSecond, refillPeriodMicros, DEFAULT_FAIRNESS, DEFAULT_MODE,
53         DEFAULT_AUTOTUNE);
54   }
55 
56   /**
57    * RateLimiter constructor
58    *
59    * @param rateBytesPerSecond this is the only parameter you want to set
60    *     most of the time. It controls the total write rate of compaction
61    *     and flush in bytes per second. Currently, RocksDB does not enforce
62    *     rate limit for anything other than flush and compaction, e.g. write to
63    *     WAL.
64    * @param refillPeriodMicros this controls how often tokens are refilled. For
65    *     example,
66    *     when rate_bytes_per_sec is set to 10MB/s and refill_period_us is set to
67    *     100ms, then 1MB is refilled every 100ms internally. Larger value can
68    *     lead to burstier writes while smaller value introduces more CPU
69    *     overhead. The default of 100,000ms should work for most cases.
70    * @param fairness RateLimiter accepts high-pri requests and low-pri requests.
71    *     A low-pri request is usually blocked in favor of hi-pri request.
72    *     Currently, RocksDB assigns low-pri to request from compaction and
73    *     high-pri to request from flush. Low-pri requests can get blocked if
74    *     flush requests come in continuously. This fairness parameter grants
75    *     low-pri requests permission by fairness chance even though high-pri
76    *     requests exist to avoid starvation.
77    *     You should be good by leaving it at default 10.
78    */
RateLimiter(final long rateBytesPerSecond, final long refillPeriodMicros, final int fairness)79   public RateLimiter(final long rateBytesPerSecond,
80       final long refillPeriodMicros, final int fairness) {
81     this(rateBytesPerSecond, refillPeriodMicros, fairness, DEFAULT_MODE,
82         DEFAULT_AUTOTUNE);
83   }
84 
85   /**
86    * RateLimiter constructor
87    *
88    * @param rateBytesPerSecond this is the only parameter you want to set
89    *     most of the time. It controls the total write rate of compaction
90    *     and flush in bytes per second. Currently, RocksDB does not enforce
91    *     rate limit for anything other than flush and compaction, e.g. write to
92    *     WAL.
93    * @param refillPeriodMicros this controls how often tokens are refilled. For
94    *     example,
95    *     when rate_bytes_per_sec is set to 10MB/s and refill_period_us is set to
96    *     100ms, then 1MB is refilled every 100ms internally. Larger value can
97    *     lead to burstier writes while smaller value introduces more CPU
98    *     overhead. The default of 100,000ms should work for most cases.
99    * @param fairness RateLimiter accepts high-pri requests and low-pri requests.
100    *     A low-pri request is usually blocked in favor of hi-pri request.
101    *     Currently, RocksDB assigns low-pri to request from compaction and
102    *     high-pri to request from flush. Low-pri requests can get blocked if
103    *     flush requests come in continuously. This fairness parameter grants
104    *     low-pri requests permission by fairness chance even though high-pri
105    *     requests exist to avoid starvation.
106    *     You should be good by leaving it at default 10.
107    * @param rateLimiterMode indicates which types of operations count against
108    *     the limit.
109    */
RateLimiter(final long rateBytesPerSecond, final long refillPeriodMicros, final int fairness, final RateLimiterMode rateLimiterMode)110   public RateLimiter(final long rateBytesPerSecond,
111       final long refillPeriodMicros, final int fairness,
112       final RateLimiterMode rateLimiterMode) {
113     this(rateBytesPerSecond, refillPeriodMicros, fairness, rateLimiterMode,
114         DEFAULT_AUTOTUNE);
115   }
116 
117   /**
118    * RateLimiter constructor
119    *
120    * @param rateBytesPerSecond this is the only parameter you want to set
121    *     most of the time. It controls the total write rate of compaction
122    *     and flush in bytes per second. Currently, RocksDB does not enforce
123    *     rate limit for anything other than flush and compaction, e.g. write to
124    *     WAL.
125    * @param refillPeriodMicros this controls how often tokens are refilled. For
126    *     example,
127    *     when rate_bytes_per_sec is set to 10MB/s and refill_period_us is set to
128    *     100ms, then 1MB is refilled every 100ms internally. Larger value can
129    *     lead to burstier writes while smaller value introduces more CPU
130    *     overhead. The default of 100,000ms should work for most cases.
131    * @param fairness RateLimiter accepts high-pri requests and low-pri requests.
132    *     A low-pri request is usually blocked in favor of hi-pri request.
133    *     Currently, RocksDB assigns low-pri to request from compaction and
134    *     high-pri to request from flush. Low-pri requests can get blocked if
135    *     flush requests come in continuously. This fairness parameter grants
136    *     low-pri requests permission by fairness chance even though high-pri
137    *     requests exist to avoid starvation.
138    *     You should be good by leaving it at default 10.
139    * @param rateLimiterMode indicates which types of operations count against
140    *     the limit.
141    * @param autoTune Enables dynamic adjustment of rate limit within the range
142    *     {@code [rate_bytes_per_sec / 20, rate_bytes_per_sec]}, according to
143    *     the recent demand for background I/O.
144    */
RateLimiter(final long rateBytesPerSecond, final long refillPeriodMicros, final int fairness, final RateLimiterMode rateLimiterMode, final boolean autoTune)145   public RateLimiter(final long rateBytesPerSecond,
146       final long refillPeriodMicros, final int fairness,
147       final RateLimiterMode rateLimiterMode, final boolean autoTune) {
148     super(newRateLimiterHandle(rateBytesPerSecond,
149         refillPeriodMicros, fairness, rateLimiterMode.getValue(), autoTune));
150   }
151 
152   /**
153    * <p>This API allows user to dynamically change rate limiter's bytes per second.
154    * REQUIRED: bytes_per_second &gt; 0</p>
155    *
156    * @param bytesPerSecond bytes per second.
157    */
setBytesPerSecond(final long bytesPerSecond)158   public void setBytesPerSecond(final long bytesPerSecond) {
159     assert(isOwningHandle());
160     setBytesPerSecond(nativeHandle_, bytesPerSecond);
161   }
162 
163   /**
164    * Returns the bytes per second.
165    *
166    * @return bytes per second.
167    */
getBytesPerSecond()168   public long getBytesPerSecond() {
169     assert(isOwningHandle());
170     return getBytesPerSecond(nativeHandle_);
171   }
172 
173   /**
174    * <p>Request for token to write bytes. If this request can not be satisfied,
175    * the call is blocked. Caller is responsible to make sure
176    * {@code bytes &lt; GetSingleBurstBytes()}.</p>
177    *
178    * @param bytes requested bytes.
179    */
request(final long bytes)180   public void request(final long bytes) {
181     assert(isOwningHandle());
182     request(nativeHandle_, bytes);
183   }
184 
185   /**
186    * <p>Max bytes can be granted in a single burst.</p>
187    *
188    * @return max bytes can be granted in a single burst.
189    */
getSingleBurstBytes()190   public long getSingleBurstBytes() {
191     assert(isOwningHandle());
192     return getSingleBurstBytes(nativeHandle_);
193   }
194 
195   /**
196    * <p>Total bytes that go through rate limiter.</p>
197    *
198    * @return total bytes that go through rate limiter.
199    */
getTotalBytesThrough()200   public long getTotalBytesThrough() {
201     assert(isOwningHandle());
202     return getTotalBytesThrough(nativeHandle_);
203   }
204 
205   /**
206    * <p>Total # of requests that go through rate limiter.</p>
207    *
208    * @return total # of requests that go through rate limiter.
209    */
getTotalRequests()210   public long getTotalRequests() {
211     assert(isOwningHandle());
212     return getTotalRequests(nativeHandle_);
213   }
214 
newRateLimiterHandle(final long rateBytesPerSecond, final long refillPeriodMicros, final int fairness, final byte rateLimiterMode, final boolean autoTune)215   private static native long newRateLimiterHandle(final long rateBytesPerSecond,
216       final long refillPeriodMicros, final int fairness,
217       final byte rateLimiterMode, final boolean autoTune);
disposeInternal(final long handle)218   @Override protected final native void disposeInternal(final long handle);
219 
setBytesPerSecond(final long handle, final long bytesPerSecond)220   private native void setBytesPerSecond(final long handle,
221       final long bytesPerSecond);
getBytesPerSecond(final long handle)222   private native long getBytesPerSecond(final long handle);
request(final long handle, final long bytes)223   private native void request(final long handle, final long bytes);
getSingleBurstBytes(final long handle)224   private native long getSingleBurstBytes(final long handle);
getTotalBytesThrough(final long handle)225   private native long getTotalBytesThrough(final long handle);
getTotalRequests(final long handle)226   private native long getTotalRequests(final long handle);
227 }
228