Skip to content

Commit

Permalink
adaptive concurrency: Add configurable jitter to minRTT calculation w…
Browse files Browse the repository at this point in the history
…indows (envoyproxy#8377)

Signed-off-by: Tony Allen <tallen@lyft.com>
  • Loading branch information
Tony Allen committed Sep 27, 2019
1 parent 77a6430 commit 1f86635
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 64 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,13 @@ message GradientControllerConfig {
// The number of requests to aggregate/sample during the minRTT recalculation window before
// updating. Defaults to 50.
google.protobuf.UInt32Value request_count = 2 [(validate.rules).uint32.gt = 0];

// Randomized time delta that will be introduced to the start of the minRTT calculation window.
// This is represented as a percentage of the interval duration. Defaults to 15%.
//
// Example: If the interval is 10s and the jitter is 15%, the next window will begin
// somewhere in the range (10s - 11.5s).
envoy.type.Percent jitter = 3;
};
MinimumRTTCalculationParams min_rtt_calc_params = 3 [(validate.rules).message.required = true];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ GradientControllerConfig::GradientControllerConfig(
proto_config)
: min_rtt_calc_interval_(std::chrono::milliseconds(
DurationUtil::durationToMilliseconds(proto_config.min_rtt_calc_params().interval()))),
jitter_pct_(
PROTOBUF_PERCENT_TO_DOUBLE_OR_DEFAULT(proto_config.min_rtt_calc_params(), jitter, 15) /
100.0),
sample_rtt_calc_interval_(std::chrono::milliseconds(DurationUtil::durationToMilliseconds(
proto_config.concurrency_limit_params().concurrency_update_interval()))),
max_concurrency_limit_(PROTOBUF_GET_WRAPPED_OR_DEFAULT(
Expand All @@ -41,10 +44,12 @@ GradientControllerConfig::GradientControllerConfig(

GradientController::GradientController(GradientControllerConfigSharedPtr config,
Event::Dispatcher& dispatcher, Runtime::Loader&,
const std::string& stats_prefix, Stats::Scope& scope)
const std::string& stats_prefix, Stats::Scope& scope,
Runtime::RandomGenerator& random)
: config_(std::move(config)), dispatcher_(dispatcher), scope_(scope),
stats_(generateStats(scope_, stats_prefix)), deferred_limit_value_(1), num_rq_outstanding_(0),
concurrency_limit_(1), latency_sample_hist_(hist_fast_alloc(), hist_free) {
stats_(generateStats(scope_, stats_prefix)), random_(random), deferred_limit_value_(1),
num_rq_outstanding_(0), concurrency_limit_(1),
latency_sample_hist_(hist_fast_alloc(), hist_free) {
min_rtt_calc_timer_ = dispatcher_.createTimer([this]() -> void { enterMinRTTSamplingWindow(); });

sample_reset_timer_ = dispatcher_.createTimer([this]() -> void {
Expand Down Expand Up @@ -98,7 +103,18 @@ void GradientController::updateMinRTT() {
deferred_limit_value_.store(0);
}

min_rtt_calc_timer_->enableTimer(config_->minRTTCalcInterval());
min_rtt_calc_timer_->enableTimer(
applyJitter(config_->minRTTCalcInterval(), config_->jitterPercent()));
}

std::chrono::milliseconds GradientController::applyJitter(std::chrono::milliseconds interval,
double jitter_pct) const {
if (jitter_pct == 0) {
return interval;
}

const uint32_t jitter_range_ms = interval.count() * jitter_pct;
return std::chrono::milliseconds(interval.count() + (random_.random() % jitter_range_ms));
}

void GradientController::resetSampleWindow() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class GradientControllerConfig {
proto_config);

std::chrono::milliseconds minRTTCalcInterval() const { return min_rtt_calc_interval_; }
double jitterPercent() const { return jitter_pct_; }
std::chrono::milliseconds sampleRTTCalcInterval() const { return sample_rtt_calc_interval_; }
uint32_t maxConcurrencyLimit() const { return max_concurrency_limit_; }
uint32_t minRTTAggregateRequestCount() const { return min_rtt_aggregate_request_count_; }
Expand All @@ -54,6 +55,9 @@ class GradientControllerConfig {
// The measured request round-trip time under ideal conditions.
const std::chrono::milliseconds min_rtt_calc_interval_;

// Randomized time delta added to the start of the minRTT calculation window.
const double jitter_pct_;

// The measured sample round-trip time from the previous time window.
const std::chrono::milliseconds sample_rtt_calc_interval_;

Expand Down Expand Up @@ -136,8 +140,8 @@ using GradientControllerConfigSharedPtr = std::shared_ptr<GradientControllerConf
class GradientController : public ConcurrencyController {
public:
GradientController(GradientControllerConfigSharedPtr config, Event::Dispatcher& dispatcher,
Runtime::Loader& runtime, const std::string& stats_prefix,
Stats::Scope& scope);
Runtime::Loader& runtime, const std::string& stats_prefix, Stats::Scope& scope,
Runtime::RandomGenerator& random);

// ConcurrencyController.
RequestForwardingAction forwardingDecision() override;
Expand All @@ -159,11 +163,14 @@ class GradientController : public ConcurrencyController {
concurrency_limit_.store(new_limit);
stats_.concurrency_limit_.set(concurrency_limit_.load());
}
std::chrono::milliseconds applyJitter(std::chrono::milliseconds interval,
double jitter_pct) const;

const GradientControllerConfigSharedPtr config_;
Event::Dispatcher& dispatcher_;
Stats::Scope& scope_;
GradientControllerStats stats_;
Runtime::RandomGenerator& random_;

// Protects data related to latency sampling and RTT values. In addition to protecting the latency
// sample histogram, the mutex ensures that the minRTT calculation window and the sample window
Expand Down
Loading

0 comments on commit 1f86635

Please sign in to comment.