diff options
author | rtenneti@chromium.org <rtenneti@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-01-30 04:03:04 +0000 |
---|---|---|
committer | rtenneti@chromium.org <rtenneti@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-01-30 04:03:04 +0000 |
commit | c5e1aca90ddc180362e0663648c482b874436adf (patch) | |
tree | 5f2a71349aaebe5fae92f5651ae8f5bf7a0db366 /net/quic/congestion_control | |
parent | f13d7a712f2455a7e9699c12d7ac4d4c604c819f (diff) | |
download | chromium_src-c5e1aca90ddc180362e0663648c482b874436adf.zip chromium_src-c5e1aca90ddc180362e0663648c482b874436adf.tar.gz chromium_src-c5e1aca90ddc180362e0663648c482b874436adf.tar.bz2 |
Land Recent QUIC Changes.
Cleanup: remove BlockedWriterInterface from QuicPacketWriter.
No behavior changes.
Merge internal change: 60499316
https://codereview.chromium.org/135363006/
Properly trigger OnCanWrite processing from PacketDroppingTestWriter.
Re-enable the LargePostWithPacketLossAndBlockedSocket test.
Testing only.
Dialing back the loss from 30% to 10% seems to have stabilized the test.
Merge internal change: 60479729
https://codereview.chromium.org/131503016/
Use LOG_IF instead of LOG_IF_FIRST_N in a few places, as per avd's
suggestion.
Merge internal change: 60382807
https://codereview.chromium.org/149163004/
Change the default RTT from 60ms to 100ms, which is more typical of
internal server's.
Merge internal change: 60366147
https://codereview.chromium.org/146583006/
Remove an impossible check in QuicConnection for when a packet is
retransmitted before it is sent.
Updating the tests also found and fixed an edge case where a truncated
ack could cause the SentPacketManager to raise the high water mark above
a pending packet.
Merge internal change: 60169343
https://codereview.chromium.org/145123003/
Export primary insecure and secure QUIC config id via internal server
status pages.
Merge internal change: 60108488
https://codereview.chromium.org/137423015/
Export SCIDs, QUIC secret seed names and orbits to varz.
Merge internal change: 60107113
https://codereview.chromium.org/144033006/
Refactor QuicConnection to use explicit notification for getting onto
the write blocked list. Remove the PacketWriter interface from
QuicDispatcher.
Merge internal change: 60103466
Fix build. Build got broken by a race between presubmit tests and me
editing the file that was in the process of being submitted. :(
Merge internal change: 60104577
https://codereview.chromium.org/149263002/
Remove the word Payload from AddFrame methods in QUIC framer.
Merge internal change: 60101552
https://codereview.chromium.org/131513022/
Fixes QUIC's Cubic sender to use correct alpha when in Reno mode.
Merge internal change: 60088487
https://codereview.chromium.org/136453013/
Add DFATALs to QuicFramer branches where packet creation fails.
Merge internal change: 60077767
https://codereview.chromium.org/148073002/
Fix a QUIC bug where previously undecryptable packets were not decrypted
before sending out an ack when the encryption level changed.
Merge internal change: 60051502
Added logging for all frame types.
Added code to dump frames and packet_headers. Changes to make
QuicHttpStreamTest work.
https://codereview.chromium.org/144063012/
R=rch@chromium.org
Review URL: https://codereview.chromium.org/146033003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@247827 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/quic/congestion_control')
-rw-r--r-- | net/quic/congestion_control/cubic.cc | 46 | ||||
-rw-r--r-- | net/quic/congestion_control/cubic_test.cc | 35 | ||||
-rw-r--r-- | net/quic/congestion_control/tcp_cubic_sender.cc | 2 | ||||
-rw-r--r-- | net/quic/congestion_control/tcp_cubic_sender_test.cc | 4 |
4 files changed, 57 insertions, 30 deletions
diff --git a/net/quic/congestion_control/cubic.cc b/net/quic/congestion_control/cubic.cc index 2212098..938faaea 100644 --- a/net/quic/congestion_control/cubic.cc +++ b/net/quic/congestion_control/cubic.cc @@ -26,10 +26,26 @@ const int kCubeScale = 40; // 1024*1024^3 (first 1024 is from 0.100^3) const int kCubeCongestionWindowScale = 410; const uint64 kCubeFactor = (GG_UINT64_C(1) << kCubeScale) / kCubeCongestionWindowScale; -const uint32 kBetaSPDY = 939; // Back off factor after loss for SPDY, reduces - // the CWND by 1/12th. -const uint32 kBetaLastMax = 871; // Additional back off factor after loss for - // the stored max value. + +const uint32 kNumConnections = 2; +const float kBeta = static_cast<float>(0.7); // Default Cubic backoff factor. +// Additional backoff factor when loss occurs in the concave part of the Cubic +// curve. This additional backoff factor is expected to give up bandwidth to +// new concurrent flows and speed up convergence. +const float kBetaLastMax = static_cast<float>(0.85); + +// kNConnectionBeta is the backoff factor after loss for our N-connection +// emulation, which emulates the effective backoff of an ensemble of N TCP-Reno +// connections on a single loss event. The effective multiplier is computed as: +const float kNConnectionBeta = (kNumConnections - 1 + kBeta) / kNumConnections; + +// TCPFriendly alpha is described in Section 3.3 of the CUBIC paper. Note that +// kBeta here is a cwnd multiplier, and is equal to 1-beta from the CUBIC paper. +// We derive the equivalent kNConnectionAlpha for an N-connection emulation as: +const float kNConnectionAlpha = 3 * kNumConnections * kNumConnections * + (1 - kNConnectionBeta) / (1 + kNConnectionBeta); +// TODO(jri): Compute kNConnectionBeta and kNConnectionAlpha from +// number of active streams. } // namespace Cubic::Cubic(const QuicClock* clock) @@ -57,12 +73,12 @@ QuicTcpCongestionWindow Cubic::CongestionWindowAfterPacketLoss( // We never reached the old max, so assume we are competing with another // flow. Use our extra back off factor to allow the other flow to go up. last_max_congestion_window_ = - (kBetaLastMax * current_congestion_window) >> 10; + static_cast<int>(kBetaLastMax * current_congestion_window); } else { last_max_congestion_window_ = current_congestion_window; } epoch_ = QuicTime::Zero(); // Reset time. - return (current_congestion_window * kBetaSPDY) >> 10; + return static_cast<int>(current_congestion_window * kNConnectionBeta); } QuicTcpCongestionWindow Cubic::CongestionWindowAfterAck( @@ -114,13 +130,21 @@ QuicTcpCongestionWindow Cubic::CongestionWindowAfterAck( // We have a new cubic congestion window. last_target_congestion_window_ = target_congestion_window; - // Update estimated TCP congestion_window. - // Note: we do a normal Reno congestion avoidance calculation not the - // calculation described in section 3.3 TCP-friendly region of the document. - while (acked_packets_count_ >= estimated_tcp_congestion_window_) { - acked_packets_count_ -= estimated_tcp_congestion_window_; + DCHECK_LT(0u, estimated_tcp_congestion_window_); + // With dynamic beta/alpha based on number of active streams, it is possible + // for the required_ack_count to become much lower than acked_packets_count_ + // suddenly, leading to more than one iteration through the following loop. + while (true) { + // Update estimated TCP congestion_window. + uint32 required_ack_count = + estimated_tcp_congestion_window_ / kNConnectionAlpha; + if (acked_packets_count_ < required_ack_count) { + break; + } + acked_packets_count_ -= required_ack_count; estimated_tcp_congestion_window_++; } + // Compute target congestion_window based on cubic target and estimated TCP // congestion_window, use highest (fastest). if (target_congestion_window < estimated_tcp_congestion_window_) { diff --git a/net/quic/congestion_control/cubic_test.cc b/net/quic/congestion_control/cubic_test.cc index 8e0d8e9..00bd37b 100644 --- a/net/quic/congestion_control/cubic_test.cc +++ b/net/quic/congestion_control/cubic_test.cc @@ -11,6 +11,12 @@ namespace net { namespace test { +const float kBeta = static_cast<float>(0.7); // Default Cubic backoff factor. +const uint32 kNumConnections = 2; +const float kNConnectionBeta = (kNumConnections - 1 + kBeta) / kNumConnections; +const float kNConnectionAlpha = 3 * kNumConnections * kNumConnections * + (1 - kNConnectionBeta) / (1 + kNConnectionBeta); + class CubicTest : public ::testing::Test { protected: CubicTest() @@ -24,7 +30,7 @@ class CubicTest : public ::testing::Test { Cubic cubic_; }; -TEST_F(CubicTest, AboveOrgin) { +TEST_F(CubicTest, AboveOrigin) { // Convex growth. const QuicTime::Delta rtt_min = hundred_ms_; uint32 current_cwnd = 10; @@ -36,14 +42,14 @@ TEST_F(CubicTest, AboveOrgin) { current_cwnd = expected_cwnd; // Normal TCP phase. for (int i = 0; i < 48; ++i) { - for (uint32 n = 1; n < current_cwnd; ++n) { + for (uint32 n = 1; n < current_cwnd / kNConnectionAlpha; ++n) { // Call once per ACK. - EXPECT_EQ(current_cwnd, - cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min)); + EXPECT_NEAR(current_cwnd, + cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min), 1); } clock_.AdvanceTime(hundred_ms_); current_cwnd = cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min); - EXPECT_EQ(expected_cwnd, current_cwnd); + EXPECT_NEAR(expected_cwnd, current_cwnd, 1); expected_cwnd++; } // Cubic phase. @@ -70,15 +76,15 @@ TEST_F(CubicTest, LossEvents) { clock_.AdvanceTime(one_ms_); EXPECT_EQ(expected_cwnd, cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min)); - expected_cwnd = current_cwnd * 939 / 1024; + expected_cwnd = static_cast<int>(current_cwnd * kNConnectionBeta); EXPECT_EQ(expected_cwnd, cubic_.CongestionWindowAfterPacketLoss(current_cwnd)); - expected_cwnd = current_cwnd * 939 / 1024; + expected_cwnd = static_cast<int>(current_cwnd * kNConnectionBeta); EXPECT_EQ(expected_cwnd, cubic_.CongestionWindowAfterPacketLoss(current_cwnd)); } -TEST_F(CubicTest, BelowOrgin) { +TEST_F(CubicTest, BelowOrigin) { // Concave growth. const QuicTime::Delta rtt_min = hundred_ms_; uint32 current_cwnd = 422; @@ -87,23 +93,18 @@ TEST_F(CubicTest, BelowOrgin) { clock_.AdvanceTime(one_ms_); EXPECT_EQ(expected_cwnd, cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min)); - expected_cwnd = current_cwnd * 939 / 1024; + expected_cwnd = static_cast<int>(current_cwnd * kNConnectionBeta); EXPECT_EQ(expected_cwnd, cubic_.CongestionWindowAfterPacketLoss(current_cwnd)); current_cwnd = expected_cwnd; - // First update after epoch. + // First update after loss to initialize the epoch. current_cwnd = cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min); // Cubic phase. - for (int i = 0; i < 54; ++i) { - for (uint32 n = 1; n < current_cwnd; ++n) { - // Call once per ACK. - EXPECT_EQ(current_cwnd, - cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min)); - } + for (int i = 0; i < 40 ; ++i) { clock_.AdvanceTime(hundred_ms_); current_cwnd = cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min); } - expected_cwnd = 440; + expected_cwnd = 422; EXPECT_EQ(expected_cwnd, current_cwnd); } diff --git a/net/quic/congestion_control/tcp_cubic_sender.cc b/net/quic/congestion_control/tcp_cubic_sender.cc index a978cf6..b44d2da 100644 --- a/net/quic/congestion_control/tcp_cubic_sender.cc +++ b/net/quic/congestion_control/tcp_cubic_sender.cc @@ -24,7 +24,7 @@ const QuicByteCount kDefaultReceiveWindow = 64000; const int64 kInitialCongestionWindow = 10; const int kMaxBurstLength = 3; // Constants used for RTT calculation. -const int kInitialRttMs = 60; // At a typical RTT 60 ms. +const int kInitialRttMs = 100; // At a typical RTT 100 ms. const float kAlpha = 0.125f; const float kOneMinusAlpha = (1 - kAlpha); const float kBeta = 0.25f; diff --git a/net/quic/congestion_control/tcp_cubic_sender_test.cc b/net/quic/congestion_control/tcp_cubic_sender_test.cc index 9faecc4..88921ba 100644 --- a/net/quic/congestion_control/tcp_cubic_sender_test.cc +++ b/net/quic/congestion_control/tcp_cubic_sender_test.cc @@ -498,7 +498,9 @@ TEST_F(TcpCubicSenderTest, TcpRenoMaxCongestionWindow) { TEST_F(TcpCubicSenderTest, TcpCubicMaxCongestionWindow) { const QuicTcpCongestionWindow kMaxCongestionWindowTCP = 50; - const int kNumberOfAcks = 1000; + // Set to 10000 to compensate for small cubic alpha. + const int kNumberOfAcks = 10000; + sender_.reset( new TcpCubicSenderPeer(&clock_, false, kMaxCongestionWindowTCP)); |