diff --git a/fdbclient/ServerKnobs.cpp b/fdbclient/ServerKnobs.cpp index 63ee03ac7f..7118e1bb89 100644 --- a/fdbclient/ServerKnobs.cpp +++ b/fdbclient/ServerKnobs.cpp @@ -557,7 +557,9 @@ void ServerKnobs::initialize(Randomize randomize, ClientKnobs* clientKnobs, IsSi init( START_TRANSACTION_MAX_TRANSACTIONS_TO_START, 100000 ); init( START_TRANSACTION_MAX_REQUESTS_TO_START, 10000 ); init( START_TRANSACTION_RATE_WINDOW, 2.0 ); + init( TAG_THROTTLE_RATE_WINDOW, 2.0 ); init( START_TRANSACTION_MAX_EMPTY_QUEUE_BUDGET, 10.0 ); + init( TAG_THROTTLE_MAX_EMPTY_QUEUE_BUDGET, 10.0 ); init( START_TRANSACTION_MAX_QUEUE_SIZE, 1e6 ); init( KEY_LOCATION_MAX_QUEUE_SIZE, 1e6 ); init( TENANT_ID_REQUEST_MAX_QUEUE_SIZE, 1e6 ); diff --git a/fdbclient/include/fdbclient/ServerKnobs.h b/fdbclient/include/fdbclient/ServerKnobs.h index ebc9174abf..2620dfd636 100644 --- a/fdbclient/include/fdbclient/ServerKnobs.h +++ b/fdbclient/include/fdbclient/ServerKnobs.h @@ -504,7 +504,9 @@ public: double START_TRANSACTION_MAX_TRANSACTIONS_TO_START; int START_TRANSACTION_MAX_REQUESTS_TO_START; double START_TRANSACTION_RATE_WINDOW; + double TAG_THROTTLE_RATE_WINDOW; double START_TRANSACTION_MAX_EMPTY_QUEUE_BUDGET; + double TAG_THROTTLE_MAX_EMPTY_QUEUE_BUDGET; int START_TRANSACTION_MAX_QUEUE_SIZE; int KEY_LOCATION_MAX_QUEUE_SIZE; int TENANT_ID_REQUEST_MAX_QUEUE_SIZE; diff --git a/fdbserver/GrvProxyServer.actor.cpp b/fdbserver/GrvProxyServer.actor.cpp index a9bb11677b..c150dfdbca 100644 --- a/fdbserver/GrvProxyServer.actor.cpp +++ b/fdbserver/GrvProxyServer.actor.cpp @@ -833,8 +833,12 @@ ACTOR static Future transactionStarter(GrvProxyInterface proxy, state int64_t transactionCount = 0; state int64_t batchTransactionCount = 0; - state GrvTransactionRateInfo normalRateInfo(10); - state GrvTransactionRateInfo batchRateInfo(0); + state GrvTransactionRateInfo normalRateInfo(SERVER_KNOBS->START_TRANSACTION_RATE_WINDOW, + SERVER_KNOBS->START_TRANSACTION_MAX_EMPTY_QUEUE_BUDGET, + /*rate=*/10); + state GrvTransactionRateInfo batchRateInfo(SERVER_KNOBS->START_TRANSACTION_RATE_WINDOW, + SERVER_KNOBS->START_TRANSACTION_MAX_EMPTY_QUEUE_BUDGET, + /*rate=*/0); state Deque systemQueue; state Deque defaultQueue; diff --git a/fdbserver/GrvProxyTagThrottler.actor.cpp b/fdbserver/GrvProxyTagThrottler.actor.cpp index 485dad38b5..2cd561d460 100644 --- a/fdbserver/GrvProxyTagThrottler.actor.cpp +++ b/fdbserver/GrvProxyTagThrottler.actor.cpp @@ -40,7 +40,8 @@ void GrvProxyTagThrottler::TagQueue::setRate(double rate) { if (rateInfo.present()) { rateInfo.get().setRate(rate); } else { - rateInfo = GrvTransactionRateInfo(rate); + rateInfo = GrvTransactionRateInfo( + SERVER_KNOBS->TAG_THROTTLE_RATE_WINDOW, SERVER_KNOBS->TAG_THROTTLE_MAX_EMPTY_QUEUE_BUDGET, rate); } } diff --git a/fdbserver/GrvTransactionRateInfo.actor.cpp b/fdbserver/GrvTransactionRateInfo.actor.cpp index 75778bee4e..eb4b8e8c90 100644 --- a/fdbserver/GrvTransactionRateInfo.actor.cpp +++ b/fdbserver/GrvTransactionRateInfo.actor.cpp @@ -24,9 +24,9 @@ #include "flow/UnitTest.h" #include "flow/actorcompiler.h" // must be last include -GrvTransactionRateInfo::GrvTransactionRateInfo(double rate) - : rate(rate), smoothRate(SERVER_KNOBS->START_TRANSACTION_RATE_WINDOW), - smoothReleased(SERVER_KNOBS->START_TRANSACTION_RATE_WINDOW) { +GrvTransactionRateInfo::GrvTransactionRateInfo(double rateWindow, double maxEmptyQueueBudget, double rate) + : rateWindow(rateWindow), maxEmptyQueueBudget(maxEmptyQueueBudget), rate(rate), smoothRate(rateWindow), + smoothReleased(rateWindow) { smoothRate.setTotal(rate); } @@ -50,14 +50,14 @@ void GrvTransactionRateInfo::endReleaseWindow(int64_t numStarted, bool queueEmpt // accumulate budget over time in the case that our batches are too big to take advantage of the rate window based // limits. // - // Note that "rate window" here indicates a period of SERVER_KNOBS->START_TRANSACTION_RATE_WINDOW seconds, + // Note that "rate window" here indicates a period of rateWindow seconds, // whereas "release window" is the period between wait statements, with duration indicated by "elapsed." - budget = std::max(0.0, budget + elapsed * (limit - numStarted) / SERVER_KNOBS->START_TRANSACTION_RATE_WINDOW); + budget = std::max(0.0, budget + elapsed * (limit - numStarted) / rateWindow); // If we are emptying out the queue of requests, then we don't need to carry much budget forward // If we did keep accumulating budget, then our responsiveness to changes in workflow could be compromised if (queueEmpty) { - budget = std::min(budget, SERVER_KNOBS->START_TRANSACTION_MAX_EMPTY_QUEUE_BUDGET); + budget = std::min(budget, maxEmptyQueueBudget); } smoothReleased.addDelta(numStarted); @@ -91,7 +91,7 @@ void GrvTransactionRateInfo::startReleaseWindow() { // Limit can be negative in the event that we are releasing more transactions than we are allowed (due to the // use of our budget or because of higher priority transactions). double releaseRate = smoothRate.smoothTotal() - smoothReleased.smoothRate(); - limit = SERVER_KNOBS->START_TRANSACTION_RATE_WINDOW * releaseRate; + limit = rateWindow * releaseRate; } static bool isNear(double desired, int64_t actual) { @@ -112,7 +112,7 @@ ACTOR static Future mockClient(GrvTransactionRateInfo* rateInfo, double de // Rate limit set at 10, but client attempts 20 transactions per second. // Client should be throttled to only 10 transactions per second. TEST_CASE("/GrvTransactionRateInfo/Simple") { - state GrvTransactionRateInfo rateInfo; + state GrvTransactionRateInfo rateInfo(/*rateWindow=*/2.0, /*maxEmptyQueueBudget=*/100, /*rate=*/10); state int64_t counter; rateInfo.setRate(10.0); wait(timeout(mockClient(&rateInfo, 20.0, &counter), 60.0, Void())); diff --git a/fdbserver/include/fdbserver/GrvProxyTagThrottler.h b/fdbserver/include/fdbserver/GrvProxyTagThrottler.h index aacdf36bf3..ee6d55f3c9 100644 --- a/fdbserver/include/fdbserver/GrvProxyTagThrottler.h +++ b/fdbserver/include/fdbserver/GrvProxyTagThrottler.h @@ -55,7 +55,10 @@ class GrvProxyTagThrottler { Deque requests; TagQueue() = default; - explicit TagQueue(double rate) : rateInfo(rate) {} + explicit TagQueue(double rate) + : rateInfo(GrvTransactionRateInfo(SERVER_KNOBS->TAG_THROTTLE_RATE_WINDOW, + SERVER_KNOBS->TAG_THROTTLE_MAX_EMPTY_QUEUE_BUDGET, + rate)) {} void setRate(double rate); bool isMaxThrottled(double maxThrottleDuration) const; diff --git a/fdbserver/include/fdbserver/GrvTransactionRateInfo.h b/fdbserver/include/fdbserver/GrvTransactionRateInfo.h index 19b3e0839b..83ccc9c6be 100644 --- a/fdbserver/include/fdbserver/GrvTransactionRateInfo.h +++ b/fdbserver/include/fdbserver/GrvTransactionRateInfo.h @@ -34,7 +34,9 @@ // // Smoothers are used to avoid turbulent throttling behaviour. class GrvTransactionRateInfo { - double rate = 0.0; + double rateWindow{ 1.0 }; + double maxEmptyQueueBudget{ 0.0 }; + double rate{ 0.0 }; double limit{ 0.0 }; double budget{ 0.0 }; bool disabled{ true }; @@ -42,7 +44,7 @@ class GrvTransactionRateInfo { Smoother smoothReleased; public: - explicit GrvTransactionRateInfo(double rate = 0.0); + GrvTransactionRateInfo(double rateWindow, double maxEmptyQueueBudget, double rate); // Determines the number of transactions that this proxy is allowed to release // in this release window.