Skip to content

Commit f227973

Browse files
committed
Reimplement rate limiter
1 parent 8941e7f commit f227973

File tree

1 file changed

+26
-27
lines changed

1 file changed

+26
-27
lines changed

utils/rate_limit.h

Lines changed: 26 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -10,66 +10,65 @@
1010

1111
#include <algorithm>
1212
#include <chrono>
13-
#include <cstdio>
1413
#include <mutex>
15-
#include <ratio>
1614
#include <thread>
1715

1816
namespace ycsbc {
1917

2018
namespace utils {
2119

22-
// Token bucket rate limiter for single client
20+
// Token bucket rate limiter for single client.
21+
// Units: rate_ = tokens/sec, bucket_ = tokens.
2322
class RateLimiter {
2423
public:
25-
RateLimiter(int64_t r, int64_t b) : r_(r * TOKEN_PRECISION), b_(b * TOKEN_PRECISION), tokens_(0), last_(Clock::now()) {}
24+
RateLimiter(int64_t r, int64_t b)
25+
: rate_(static_cast<double>(r)),
26+
bucket_(static_cast<double>(b)),
27+
tokens_(0.0),
28+
last_(Clock::now()) {}
2629

2730
inline void Consume(int64_t n) {
2831
std::unique_lock<std::mutex> lock(mutex_);
2932

30-
if (r_ <= 0) {
33+
if (rate_ <= 0.0) {
3134
return;
3235
}
3336

34-
// refill tokens
35-
auto now = Clock::now();
36-
auto diff = std::chrono::duration_cast<Duration>(now - last_);
37-
tokens_ = std::min(b_, tokens_ + diff.count() * r_ / 1000000000);
38-
last_ = now;
37+
RefillLocked();
3938

4039
// check tokens
41-
tokens_ -= n * TOKEN_PRECISION;
40+
tokens_ -= static_cast<double>(n);
4241

4342
// sleep
44-
if (tokens_ < 0) {
43+
if (tokens_ < 0.0) {
4544
lock.unlock();
46-
int64_t wait_time = -tokens_ * 1000000000 / r_;
47-
std::this_thread::sleep_for(std::chrono::nanoseconds(wait_time));
45+
const auto wait_time = Duration(-tokens_ / rate_);
46+
std::this_thread::sleep_for(wait_time);
4847
}
4948
}
5049

5150
inline void SetRate(int64_t r) {
5251
std::lock_guard<std::mutex> lock(mutex_);
5352

54-
// refill tokens
55-
auto now = Clock::now();
56-
auto diff = std::chrono::duration_cast<Duration>(now - last_);
57-
tokens_ = std::min(b_, tokens_ + diff.count() * r_ * TOKEN_PRECISION / 1000000000);
58-
last_ = now;
59-
60-
// set rate
61-
r_ = r * TOKEN_PRECISION;
53+
RefillLocked();
54+
rate_ = static_cast<double>(r);
6255
}
6356

6457
private:
6558
using Clock = std::chrono::steady_clock;
66-
using Duration = std::chrono::nanoseconds;
67-
static constexpr int64_t TOKEN_PRECISION = 10000;
59+
using Duration = std::chrono::duration<double>;
60+
61+
inline void RefillLocked() {
62+
auto now = Clock::now();
63+
Duration diff = now - last_;
64+
tokens_ = std::min(bucket_, tokens_ + diff.count() * rate_);
65+
last_ = now;
66+
}
6867

6968
std::mutex mutex_;
70-
int64_t r_;
71-
int64_t b_;
72-
int64_t tokens_;
69+
double rate_;
70+
double bucket_;
71+
double tokens_;
7372
Clock::time_point last_;
7473
};
7574

0 commit comments

Comments
 (0)