1
0
mirror of https://github.com/facebookincubator/mvfst.git synced 2025-11-09 10:00:57 +03:00

Differentiate ACK_FREQUENCY policy early in connection.

Summary: This changes the experimental behavior of BBR sending ACK_FREQUENCY frames. Now instead of using the static ack eliciting threshold, early in the connection BBR will set the threshold to 2 which has been empirically shown to be a good "initial" value.

Reviewed By: jbeshay

Differential Revision: D40438721

fbshipit-source-id: 184b8025581b6152eea97f9b557b6343d980322d
This commit is contained in:
Matt Joras
2022-10-17 17:54:45 -07:00
committed by Facebook GitHub Bot
parent 5ed1febddc
commit c8f357156e
6 changed files with 37 additions and 13 deletions

View File

@@ -268,13 +268,27 @@ void BbrCongestionController::onPacketAcked(
auto updatedMaxAckDelay = auto updatedMaxAckDelay =
std::chrono::duration_cast<std::chrono::milliseconds>(clampMaxAckDelay( std::chrono::duration_cast<std::chrono::milliseconds>(clampMaxAckDelay(
conn_, minRtt() / ackFrequencyConfig->minRttDivisor)); conn_, minRtt() / ackFrequencyConfig->minRttDivisor));
if (!lastMaxAckDelay_ || lastMaxAckDelay_.value() != updatedMaxAckDelay) { // If we are either in STARTUP or haven't sent enough packets, based on
// config.
bool shouldUseInitThreshold =
(ackFrequencyConfig->useSmallThresholdDuringStartup &&
state_ == BbrState::Startup) ||
(!ackFrequencyConfig->useSmallThresholdDuringStartup &&
(conn_.lossState.totalAckElicitingPacketsSent <=
conn_.transportSettings.rxPacketsBeforeAckInitThreshold));
// Default to 2 as the init threshold, which has been shown to be
// a good choice empirically.
uint32_t ackThreshold =
shouldUseInitThreshold ? 2 : ackFrequencyConfig->ackElicitingThreshold;
if ((!lastMaxAckDelay_ || lastMaxAckDelay_.value() != updatedMaxAckDelay) ||
(!lastAckThreshold_ || lastAckThreshold_.value() != ackThreshold)) {
requestPeerAckFrequencyChange( requestPeerAckFrequencyChange(
conn_, conn_,
ackFrequencyConfig->ackElicitingThreshold, ackThreshold,
updatedMaxAckDelay, updatedMaxAckDelay,
ackFrequencyConfig->reorderingThreshold); ackFrequencyConfig->reorderingThreshold);
lastMaxAckDelay_ = updatedMaxAckDelay; lastMaxAckDelay_ = updatedMaxAckDelay;
lastAckThreshold_ = ackThreshold;
} }
} }
updateCwnd(ack.ackedBytes, excessiveBytes); updateCwnd(ack.ackedBytes, excessiveBytes);

View File

@@ -311,6 +311,7 @@ class BbrCongestionController : public CongestionController {
// The last max ACK delay requested, so we don't end up sending // The last max ACK delay requested, so we don't end up sending
// them too frequently. // them too frequently.
folly::Optional<std::chrono::milliseconds> lastMaxAckDelay_; folly::Optional<std::chrono::milliseconds> lastMaxAckDelay_;
folly::Optional<uint32_t> lastAckThreshold_;
friend std::ostream& operator<<( friend std::ostream& operator<<(
std::ostream& os, std::ostream& os,

View File

@@ -138,7 +138,7 @@ TEST_F(BbrTest, Recovery) {
EXPECT_FALSE(bbr.inRecovery()); EXPECT_FALSE(bbr.inRecovery());
// Only one update should have been issued. // Only one update should have been issued.
ASSERT_EQ(conn.pendingEvents.frames.size(), 1); ASSERT_EQ(conn.pendingEvents.frames.size(), 1);
AckFrequencyFrame expectedFrame{0, 10, 5000, 3}; AckFrequencyFrame expectedFrame{0, 2, 5000, 3};
auto ackFrequencyFrame = auto ackFrequencyFrame =
conn.pendingEvents.frames.front().asAckFrequencyFrame(); conn.pendingEvents.frames.front().asAckFrequencyFrame();
EXPECT_EQ(expectedFrame, *ackFrequencyFrame); EXPECT_EQ(expectedFrame, *ackFrequencyFrame);

View File

@@ -1048,7 +1048,8 @@ void QuicServerTransport::registerAllTransportKnobParamHandlers() {
val, val,
ackFrequencyConfig.ackElicitingThreshold, ackFrequencyConfig.ackElicitingThreshold,
ackFrequencyConfig.reorderingThreshold, ackFrequencyConfig.reorderingThreshold,
ackFrequencyConfig.minRttDivisor); ackFrequencyConfig.minRttDivisor,
ackFrequencyConfig.useSmallThresholdDuringStartup);
// Sanity check the values. // Sanity check the values.
parseSuccess = parseSuccess && parseSuccess = parseSuccess &&
ackFrequencyConfig.ackElicitingThreshold > 1 && ackFrequencyConfig.ackElicitingThreshold > 1 &&
@@ -1063,9 +1064,11 @@ void QuicServerTransport::registerAllTransportKnobParamHandlers() {
"ackElicitingThreshold={}, " "ackElicitingThreshold={}, "
"reorderingThreshold={}, " "reorderingThreshold={}, "
"minRttDivisor={}", "minRttDivisor={}",
"useSmallThresholdDuringStartup={}",
ackFrequencyConfig.ackElicitingThreshold, ackFrequencyConfig.ackElicitingThreshold,
ackFrequencyConfig.reorderingThreshold, ackFrequencyConfig.reorderingThreshold,
ackFrequencyConfig.minRttDivisor); ackFrequencyConfig.minRttDivisor,
ackFrequencyConfig.useSmallThresholdDuringStartup);
serverTransport->conn_->transportSettings.bbrConfig serverTransport->conn_->transportSettings.bbrConfig
.ackFrequencyConfig = ackFrequencyConfig; .ackFrequencyConfig = ackFrequencyConfig;
serverTransport->conn_->transportSettings.autoAdaptiveForDsr = false; serverTransport->conn_->transportSettings.autoAdaptiveForDsr = false;

View File

@@ -4805,11 +4805,11 @@ TEST_F(QuicServerTransportTest, TestAckFrequencyPolicyKnobHandler) {
EXPECT_FALSE(server->getTransportSettings().bbrConfig.ackFrequencyConfig); EXPECT_FALSE(server->getTransportSettings().bbrConfig.ackFrequencyConfig);
server->handleKnobParams( server->handleKnobParams(
{{static_cast<uint64_t>(TransportKnobParamId::ACK_FREQUENCY_POLICY), {{static_cast<uint64_t>(TransportKnobParamId::ACK_FREQUENCY_POLICY),
"1,1,1"}}); "1,1,1,1"}});
EXPECT_FALSE(server->getTransportSettings().bbrConfig.ackFrequencyConfig); EXPECT_FALSE(server->getTransportSettings().bbrConfig.ackFrequencyConfig);
server->handleKnobParams( server->handleKnobParams(
{{static_cast<uint64_t>(TransportKnobParamId::ACK_FREQUENCY_POLICY), {{static_cast<uint64_t>(TransportKnobParamId::ACK_FREQUENCY_POLICY),
"10,3,1"}}); "10,3,1,1"}});
ASSERT_TRUE(server->getTransportSettings().bbrConfig.ackFrequencyConfig); ASSERT_TRUE(server->getTransportSettings().bbrConfig.ackFrequencyConfig);
EXPECT_EQ( EXPECT_EQ(
server->getTransportSettings() server->getTransportSettings()
@@ -4823,31 +4823,35 @@ TEST_F(QuicServerTransportTest, TestAckFrequencyPolicyKnobHandler) {
server->getTransportSettings() server->getTransportSettings()
.bbrConfig.ackFrequencyConfig->minRttDivisor, .bbrConfig.ackFrequencyConfig->minRttDivisor,
1); 1);
EXPECT_EQ(
server->getTransportSettings()
.bbrConfig.ackFrequencyConfig->useSmallThresholdDuringStartup,
true);
server->getNonConstConn() server->getNonConstConn()
.transportSettings.bbrConfig.ackFrequencyConfig.reset(); .transportSettings.bbrConfig.ackFrequencyConfig.reset();
server->handleKnobParams( server->handleKnobParams(
{{static_cast<uint64_t>(TransportKnobParamId::ACK_FREQUENCY_POLICY), {{static_cast<uint64_t>(TransportKnobParamId::ACK_FREQUENCY_POLICY),
"10,3,-1"}}); "10,3,-1,1"}});
EXPECT_FALSE(server->getTransportSettings().bbrConfig.ackFrequencyConfig); EXPECT_FALSE(server->getTransportSettings().bbrConfig.ackFrequencyConfig);
server->handleKnobParams( server->handleKnobParams(
{{static_cast<uint64_t>(TransportKnobParamId::ACK_FREQUENCY_POLICY), {{static_cast<uint64_t>(TransportKnobParamId::ACK_FREQUENCY_POLICY),
"10,-1,1"}}); "10,-1,1,1"}});
EXPECT_FALSE(server->getTransportSettings().bbrConfig.ackFrequencyConfig); EXPECT_FALSE(server->getTransportSettings().bbrConfig.ackFrequencyConfig);
server->handleKnobParams( server->handleKnobParams(
{{static_cast<uint64_t>(TransportKnobParamId::ACK_FREQUENCY_POLICY), {{static_cast<uint64_t>(TransportKnobParamId::ACK_FREQUENCY_POLICY),
"-1,3,1"}}); "-1,3,1,1"}});
EXPECT_FALSE(server->getTransportSettings().bbrConfig.ackFrequencyConfig); EXPECT_FALSE(server->getTransportSettings().bbrConfig.ackFrequencyConfig);
server->handleKnobParams( server->handleKnobParams(
{{static_cast<uint64_t>(TransportKnobParamId::ACK_FREQUENCY_POLICY), {{static_cast<uint64_t>(TransportKnobParamId::ACK_FREQUENCY_POLICY),
"10,3,0"}}); "10,3,0,1"}});
EXPECT_FALSE(server->getTransportSettings().bbrConfig.ackFrequencyConfig); EXPECT_FALSE(server->getTransportSettings().bbrConfig.ackFrequencyConfig);
server->handleKnobParams( server->handleKnobParams(
{{static_cast<uint64_t>(TransportKnobParamId::ACK_FREQUENCY_POLICY), {{static_cast<uint64_t>(TransportKnobParamId::ACK_FREQUENCY_POLICY),
"10,1,1"}}); "10,1,1,1"}});
EXPECT_FALSE(server->getTransportSettings().bbrConfig.ackFrequencyConfig); EXPECT_FALSE(server->getTransportSettings().bbrConfig.ackFrequencyConfig);
server->handleKnobParams( server->handleKnobParams(
{{static_cast<uint64_t>(TransportKnobParamId::ACK_FREQUENCY_POLICY), {{static_cast<uint64_t>(TransportKnobParamId::ACK_FREQUENCY_POLICY),
"1,3,1"}}); "1,3,1,1"}});
EXPECT_FALSE(server->getTransportSettings().bbrConfig.ackFrequencyConfig); EXPECT_FALSE(server->getTransportSettings().bbrConfig.ackFrequencyConfig);
} }

View File

@@ -48,6 +48,8 @@ struct BbrConfig {
uint64_t ackElicitingThreshold{kDefaultRxPacketsBeforeAckAfterInit}; uint64_t ackElicitingThreshold{kDefaultRxPacketsBeforeAckAfterInit};
uint64_t reorderingThreshold{kReorderingThreshold}; uint64_t reorderingThreshold{kReorderingThreshold};
uint32_t minRttDivisor{2}; uint32_t minRttDivisor{2};
// Threshold to use early in the connection.
bool useSmallThresholdDuringStartup{false};
}; };
folly::Optional<AckFrequencyConfig> ackFrequencyConfig; folly::Optional<AckFrequencyConfig> ackFrequencyConfig;
}; };