Skip to content

Commit

Permalink
Make auto-tuned rate limiter upper bound settable (#202)
Browse files Browse the repository at this point in the history
Old implementation of auto-tuned rate limiter effectively ignore the
`SetBytesPerSecond` call from user because of its adaptive nature. Change this
semantics in `WriteAmpBasedRateLimiter` by setting `max-bytes-per-sec` in
auto-tuned mode.

Signed-off-by: tabokie <xy.tao@outlook.com>
  • Loading branch information
tabokie committed Oct 24, 2020
1 parent 7e6c07d commit 6251283
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 9 deletions.
26 changes: 18 additions & 8 deletions utilities/rate_limiters/write_amp_based_rate_limiter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,17 @@ WriteAmpBasedRateLimiter::~WriteAmpBasedRateLimiter() {
}
}

// This API allows user to dynamically change rate limiter's bytes per second.
void WriteAmpBasedRateLimiter::SetBytesPerSecond(int64_t bytes_per_second) {
assert(bytes_per_second > 0);
if (auto_tuned_) {
max_bytes_per_sec_.store(bytes_per_second, std::memory_order_relaxed);
} else {
SetActualBytesPerSecond(bytes_per_second);
}
}

void WriteAmpBasedRateLimiter::SetActualBytesPerSecond(
int64_t bytes_per_second) {
rate_bytes_per_sec_ = bytes_per_second;
refill_bytes_per_period_.store(
CalculateRefillBytesPerPeriod(bytes_per_second),
Expand All @@ -91,8 +99,9 @@ void WriteAmpBasedRateLimiter::Request(int64_t bytes, const Env::IOPriority pri,
TEST_SYNC_POINT_CALLBACK("WriteAmpBasedRateLimiter::Request:1",
&rate_bytes_per_sec_);
if (auto_tuned_ && pri == Env::IO_HIGH &&
duration_highpri_bytes_through_ + bytes <=
max_bytes_per_sec_ * kSecondsPerTune) {
duration_highpri_bytes_through_ + duration_bytes_through_ + bytes <=
max_bytes_per_sec_.load(std::memory_order_relaxed) *
kSecondsPerTune) {
total_bytes_through_[Env::IO_HIGH] += bytes;
++total_requests_[Env::IO_HIGH];
duration_highpri_bytes_through_ += bytes;
Expand Down Expand Up @@ -321,12 +330,13 @@ Status WriteAmpBasedRateLimiter::Tune() {
int64_t new_bytes_per_sec =
(ratio + ratio_padding + ratio_delta_) *
std::max(highpri_bytes_sampler_.GetRecentValue(), kHighBytesLower) / 10;
new_bytes_per_sec = std::max(
kMinBytesPerSec,
std::min(new_bytes_per_sec,
max_bytes_per_sec_ - highpri_bytes_sampler_.GetRecentValue()));
new_bytes_per_sec =
std::max(kMinBytesPerSec,
std::min(new_bytes_per_sec,
max_bytes_per_sec_.load(std::memory_order_relaxed) -
highpri_bytes_sampler_.GetRecentValue()));
if (new_bytes_per_sec != prev_bytes_per_sec) {
SetBytesPerSecond(new_bytes_per_sec);
SetActualBytesPerSecond(new_bytes_per_sec);
}

duration_bytes_through_ = 0;
Expand Down
4 changes: 3 additions & 1 deletion utilities/rate_limiters/write_amp_based_rate_limiter.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class WriteAmpBasedRateLimiter : public RateLimiter {
virtual ~WriteAmpBasedRateLimiter();

// This API allows user to dynamically change rate limiter's bytes per second.
// When auto-tuned is on, this sets rate limit's upper bound instead.
virtual void SetBytesPerSecond(int64_t bytes_per_second) override;

// Request for token to write bytes. If this request can not be satisfied,
Expand Down Expand Up @@ -69,6 +70,7 @@ class WriteAmpBasedRateLimiter : public RateLimiter {
private:
void Refill();
int64_t CalculateRefillBytesPerPeriod(int64_t rate_bytes_per_sec);
void SetActualBytesPerSecond(int64_t bytes_per_second);
Status Tune();

uint64_t NowMicrosMonotonic(Env* env) {
Expand Down Expand Up @@ -104,7 +106,7 @@ class WriteAmpBasedRateLimiter : public RateLimiter {
std::deque<Req*> queue_[Env::IO_TOTAL];

bool auto_tuned_;
const int64_t max_bytes_per_sec_;
std::atomic<int64_t> max_bytes_per_sec_;
std::chrono::microseconds tuned_time_;
int64_t duration_highpri_bytes_through_;
int64_t duration_bytes_through_;
Expand Down

0 comments on commit 6251283

Please sign in to comment.