Currently there are two tickets on the fair-group used to normalize
per-request tickets -- the cost_capacity and the shares_capacity. The
former one is used to evaluate how much a request contributes to the
disk run-time capacity (a.k.a. the tokens in the buckets), while the
former one is used to calculate the accumulator -- a counter used to
balance between classes according to their shares. The shares ticket
is exactly latency_goal[us] times larger than the cost one.
It's better to remove the shares ticket and use the cost one in all
the calculations. Note, that the accumulator values instantly become
~1k times less, but for now it's fine -- the accumulator is (still)
a floating-point number.
include/seastar/core/fair_queue.hh | 5 -----
src/core/fair_queue.cc | 11 +++++------
src/core/io_queue.cc | 3 ---
tests/perf/fair_queue_perf.cc | 4 ----
tests/unit/fair_queue_test.cc | 2 --
5 files changed, 5 insertions(+), 20 deletions(-)
diff --git a/include/seastar/core/fair_queue.hh b/include/seastar/core/fair_queue.hh
index db9b9855..7f310b46 100644
--- a/include/seastar/core/fair_queue.hh
+++ b/include/seastar/core/fair_queue.hh
@@ -172,8 +172,6 @@ class fair_group {
using fair_group_atomic_rover = std::atomic<capacity_t>;
static_assert(fair_group_atomic_rover::is_always_lock_free);
- const fair_queue_ticket _shares_capacity;
-
/*
* The dF/dt <= K limitation is managed by the modified token bucket
* algo where tokens are ticket.normalize(cost_capacity), the refill
@@ -251,8 +249,6 @@ class fair_group {
struct config {
sstring label = "";
- unsigned max_weight;
- unsigned max_size;
unsigned min_weight = 0;
unsigned min_size = 0;
unsigned long weight_rate;
@@ -264,7 +260,6 @@ class fair_group {
explicit fair_group(config cfg) noexcept;
fair_group(fair_group&&) = delete;
- fair_queue_ticket shares_capacity() const noexcept { return _shares_capacity; }
fair_queue_ticket cost_capacity() const noexcept { return _cost_capacity; }
capacity_t maximum_capacity() const noexcept { return _replenish_limit; }
capacity_t grab_capacity(capacity_t cap) noexcept;
diff --git a/src/core/fair_queue.cc b/src/core/fair_queue.cc
index 3c289c9a..cabbd6e3 100644
--- a/src/core/fair_queue.cc
+++ b/src/core/fair_queue.cc
@@ -90,8 +90,7 @@ uint64_t wrapping_difference(const uint64_t& a, const uint64_t& b) noexcept {
}
fair_group::fair_group(config cfg) noexcept
- : _shares_capacity(cfg.max_weight, cfg.max_size)
- , _cost_capacity(cfg.weight_rate / std::chrono::duration_cast<rate_resolution>(std::chrono::seconds(1)).count(), cfg.size_rate / std::chrono::duration_cast<rate_resolution>(std::chrono::seconds(1)).count())
+ : _cost_capacity(cfg.weight_rate / std::chrono::duration_cast<rate_resolution>(std::chrono::seconds(1)).count(), cfg.size_rate / std::chrono::duration_cast<rate_resolution>(std::chrono::seconds(1)).count())
, _replenish_rate(cfg.rate_factor * fixed_point_factor)
, _replenish_limit(_replenish_rate * std::chrono::duration_cast<rate_resolution>(cfg.rate_limit_duration).count())
, _replenish_threshold(std::max((capacity_t)1, ticket_capacity(fair_queue_ticket(cfg.min_weight, cfg.min_size))))
@@ -101,8 +100,8 @@ fair_group::fair_group(config cfg) noexcept
, _capacity_ceil(_replenish_limit)
{
assert(!wrapping_difference(_capacity_tail.load(std::memory_order_relaxed), _capacity_head.load(std::memory_order_relaxed)));
-
seastar_logger.info("Created fair group {}, capacity shares {} rate {}, limit {}, rate {} (factor {}), threshold {}", cfg.label,
- _shares_capacity, _cost_capacity, _replenish_limit, _replenish_rate, cfg.rate_factor, _replenish_threshold);
+
seastar_logger.info("Created fair group {}, capacity rate {}, limit {}, rate {} (factor {}), threshold {}", cfg.label,
+ _cost_capacity, _replenish_limit, _replenish_rate, cfg.rate_factor, _replenish_threshold);
}
auto fair_group::grab_capacity(capacity_t cap) noexcept -> capacity_t {
@@ -214,7 +213,7 @@ void fair_queue::push_priority_class_from_idle(priority_class_data& pc) {
// duration. For this estimate how many capacity units can be
// accumulated with the current class shares per rate resulution
// and scale it up to tau.
- accumulator_t max_deviation = _group.cost_capacity().normalize(_group.shares_capacity()) / pc._shares * std::chrono::duration_cast<fair_group::rate_resolution>(_config.tau).count();
+ accumulator_t max_deviation = fair_group::fixed_point_factor / pc._shares * std::chrono::duration_cast<fair_group::rate_resolution>(_config.tau).count();
pc._accumulated = std::max(_last_accumulated - max_deviation, pc._accumulated);
_handles.push(&pc);
pc._queued = true;
@@ -371,7 +370,7 @@ void fair_queue::dispatch_requests(std::function<void(fair_queue_entry&)> cb) {
_requests_executing++;
_requests_queued--;
- auto req_cost = req._ticket.normalize(_group.shares_capacity()) / h._shares;
+ auto req_cost = (accumulator_t)_group.ticket_capacity(req._ticket) / h._shares;
auto next_accumulated = h._accumulated + req_cost;
if (std::isinf(next_accumulated)) {
for (auto& pc : _priority_classes) {
diff --git a/src/core/io_queue.cc b/src/core/io_queue.cc
index 62a949ea..f5327f82 100644
--- a/src/core/io_queue.cc
+++ b/src/core/io_queue.cc
@@ -367,13 +367,10 @@ fair_group::config io_group::make_fair_group_config(const io_queue::config& qcfg
*/
if (max_req_count < max_req_count_min) {
seastar_logger.warn("The disk request rate is too low, configuring it to {}, but you may experience latency problems", max_req_count_min);
- max_req_count = max_req_count_min;
}
fair_group::config cfg;
cfg.label = fmt::format("io-queue-{}", qcfg.devid);
- cfg.max_weight = max_req_count;
- cfg.max_size = qcfg.max_blocks_count;
cfg.min_weight = std::min(io_queue::read_request_base_count, qcfg.disk_req_write_to_read_multiplier);
cfg.min_size = std::min(io_queue::read_request_base_count, qcfg.disk_blocks_write_to_read_multiplier);
cfg.weight_rate = qcfg.req_count_rate;
diff --git a/tests/perf/fair_queue_perf.cc b/tests/perf/fair_queue_perf.cc
index 054cdfe2..d22af74b 100644
--- a/tests/perf/fair_queue_perf.cc
+++ b/tests/perf/fair_queue_perf.cc
@@ -39,8 +39,6 @@ struct local_fq_and_class {
static fair_group::config fg_config() {
fair_group::config cfg;
- cfg.max_weight = 1;
- cfg.max_size = 1;
cfg.weight_rate = std::numeric_limits<int>::max();
cfg.size_rate = std::numeric_limits<int>::max();
return cfg;
@@ -81,8 +79,6 @@ struct perf_fair_queue {
static fair_group::config fg_config() {
fair_group::config cfg;
- cfg.max_weight = smp::count;
- cfg.max_size = smp::count;
cfg.weight_rate = std::numeric_limits<int>::max();
cfg.size_rate = std::numeric_limits<int>::max();
return cfg;
diff --git a/tests/unit/fair_queue_test.cc b/tests/unit/fair_queue_test.cc
index 7e7ef902..b2e65230 100644
--- a/tests/unit/fair_queue_test.cc
+++ b/tests/unit/fair_queue_test.cc
@@ -64,8 +64,6 @@ class test_env {
static fair_group::config fg_config(unsigned cap) {
fair_group::config cfg;
- cfg.max_weight = cap;
- cfg.max_size = std::numeric_limits<int>::max();
cfg.weight_rate = 1'000'000;
cfg.size_rate = std::numeric_limits<int>::max();
cfg.rate_limit_duration = std::chrono::microseconds(cap);
--
2.20.1