| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/quic/core/congestion_control/cubic.h" | 5 #include "net/quic/core/congestion_control/cubic.h" |
| 6 | 6 |
| 7 #include <cstdint> | 7 #include <cstdint> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "net/quic/test_tools/mock_clock.h" | 10 #include "net/quic/test_tools/mock_clock.h" |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 44 const QuicTime::Delta rtt_min = hundred_ms_; | 44 const QuicTime::Delta rtt_min = hundred_ms_; |
| 45 const float rtt_min_s = rtt_min.ToMilliseconds() / 1000.0; | 45 const float rtt_min_s = rtt_min.ToMilliseconds() / 1000.0; |
| 46 QuicPacketCount current_cwnd = 10; | 46 QuicPacketCount current_cwnd = 10; |
| 47 // Without the signed-integer, cubic-convex fix, we mistakenly | 47 // Without the signed-integer, cubic-convex fix, we mistakenly |
| 48 // increment cwnd after only one_ms_ and a single ack. | 48 // increment cwnd after only one_ms_ and a single ack. |
| 49 QuicPacketCount expected_cwnd = | 49 QuicPacketCount expected_cwnd = |
| 50 fix_convex_mode_ ? current_cwnd : current_cwnd + 1; | 50 fix_convex_mode_ ? current_cwnd : current_cwnd + 1; |
| 51 // Initialize the state. | 51 // Initialize the state. |
| 52 clock_.AdvanceTime(one_ms_); | 52 clock_.AdvanceTime(one_ms_); |
| 53 const QuicTime initial_time = clock_.ApproximateNow(); | 53 const QuicTime initial_time = clock_.ApproximateNow(); |
| 54 current_cwnd = cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min); | 54 current_cwnd = |
| 55 cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min, initial_time); |
| 55 ASSERT_EQ(expected_cwnd, current_cwnd); | 56 ASSERT_EQ(expected_cwnd, current_cwnd); |
| 56 const QuicPacketCount initial_cwnd = current_cwnd; | 57 const QuicPacketCount initial_cwnd = current_cwnd; |
| 57 // Normal TCP phase. | 58 // Normal TCP phase. |
| 58 // The maximum number of expected reno RTTs can be calculated by | 59 // The maximum number of expected reno RTTs can be calculated by |
| 59 // finding the point where the cubic curve and the reno curve meet. | 60 // finding the point where the cubic curve and the reno curve meet. |
| 60 const int max_reno_rtts = | 61 const int max_reno_rtts = |
| 61 std::sqrt(kNConnectionAlpha / (.4 * rtt_min_s * rtt_min_s * rtt_min_s)) - | 62 std::sqrt(kNConnectionAlpha / (.4 * rtt_min_s * rtt_min_s * rtt_min_s)) - |
| 62 1; | 63 1; |
| 63 for (int i = 0; i < max_reno_rtts; ++i) { | 64 for (int i = 0; i < max_reno_rtts; ++i) { |
| 64 const QuicByteCount max_per_ack_cwnd = current_cwnd; | 65 const QuicByteCount max_per_ack_cwnd = current_cwnd; |
| 65 for (QuicPacketCount n = 1; n < max_per_ack_cwnd / kNConnectionAlpha; ++n) { | 66 for (QuicPacketCount n = 1; n < max_per_ack_cwnd / kNConnectionAlpha; ++n) { |
| 66 // Call once per ACK. | 67 // Call once per ACK. |
| 67 const QuicByteCount next_cwnd = | 68 const QuicByteCount next_cwnd = cubic_.CongestionWindowAfterAck( |
| 68 cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min); | 69 current_cwnd, rtt_min, clock_.ApproximateNow()); |
| 69 ASSERT_EQ(current_cwnd, next_cwnd); | 70 ASSERT_EQ(current_cwnd, next_cwnd); |
| 70 } | 71 } |
| 71 clock_.AdvanceTime(hundred_ms_); | 72 clock_.AdvanceTime(hundred_ms_); |
| 72 current_cwnd = cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min); | 73 current_cwnd = cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min, |
| 74 clock_.ApproximateNow()); |
| 73 if (fix_convex_mode_) { | 75 if (fix_convex_mode_) { |
| 74 // When we fix convex mode and the uint64 arithmetic, we | 76 // When we fix convex mode and the uint64 arithmetic, we |
| 75 // increase the expected_cwnd only after after the first 100ms, | 77 // increase the expected_cwnd only after after the first 100ms, |
| 76 // rather than after the initial 1ms. | 78 // rather than after the initial 1ms. |
| 77 expected_cwnd++; | 79 expected_cwnd++; |
| 78 ASSERT_EQ(expected_cwnd, current_cwnd); | 80 ASSERT_EQ(expected_cwnd, current_cwnd); |
| 79 } else { | 81 } else { |
| 80 ASSERT_EQ(expected_cwnd, current_cwnd); | 82 ASSERT_EQ(expected_cwnd, current_cwnd); |
| 81 expected_cwnd++; | 83 expected_cwnd++; |
| 82 } | 84 } |
| 83 } | 85 } |
| 84 // Cubic phase. | 86 // Cubic phase. |
| 85 for (int i = 0; i < 52; ++i) { | 87 for (int i = 0; i < 52; ++i) { |
| 86 for (QuicPacketCount n = 1; n < current_cwnd; ++n) { | 88 for (QuicPacketCount n = 1; n < current_cwnd; ++n) { |
| 87 // Call once per ACK. | 89 // Call once per ACK. |
| 88 ASSERT_EQ(current_cwnd, | 90 ASSERT_EQ(current_cwnd, |
| 89 cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min)); | 91 cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min, |
| 92 clock_.ApproximateNow())); |
| 90 } | 93 } |
| 91 clock_.AdvanceTime(hundred_ms_); | 94 clock_.AdvanceTime(hundred_ms_); |
| 92 current_cwnd = cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min); | 95 current_cwnd = cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min, |
| 96 clock_.ApproximateNow()); |
| 93 } | 97 } |
| 94 // Total time elapsed so far; add min_rtt (0.1s) here as well. | 98 // Total time elapsed so far; add min_rtt (0.1s) here as well. |
| 95 const float elapsed_time_ms = | 99 const float elapsed_time_ms = |
| 96 (clock_.ApproximateNow() - initial_time).ToMilliseconds() + | 100 (clock_.ApproximateNow() - initial_time).ToMilliseconds() + |
| 97 rtt_min.ToMilliseconds(); | 101 rtt_min.ToMilliseconds(); |
| 98 const float elapsed_time_s = elapsed_time_ms / 1000.0; | 102 const float elapsed_time_s = elapsed_time_ms / 1000.0; |
| 99 // |expected_cwnd| is initial value of cwnd + K * t^3, where K = 0.4. | 103 // |expected_cwnd| is initial value of cwnd + K * t^3, where K = 0.4. |
| 100 expected_cwnd = | 104 expected_cwnd = |
| 101 initial_cwnd + | 105 initial_cwnd + |
| 102 (elapsed_time_s * elapsed_time_s * elapsed_time_s * 410) / 1024; | 106 (elapsed_time_s * elapsed_time_s * elapsed_time_s * 410) / 1024; |
| 103 EXPECT_EQ(expected_cwnd, current_cwnd); | 107 EXPECT_EQ(expected_cwnd, current_cwnd); |
| 104 } | 108 } |
| 105 | 109 |
| 106 TEST_P(CubicTest, LossEvents) { | 110 TEST_P(CubicTest, LossEvents) { |
| 107 const QuicTime::Delta rtt_min = hundred_ms_; | 111 const QuicTime::Delta rtt_min = hundred_ms_; |
| 108 QuicPacketCount current_cwnd = 422; | 112 QuicPacketCount current_cwnd = 422; |
| 109 // Without the signed-integer, cubic-convex fix, we mistakenly | 113 // Without the signed-integer, cubic-convex fix, we mistakenly |
| 110 // increment cwnd after only one_ms_ and a single ack. | 114 // increment cwnd after only one_ms_ and a single ack. |
| 111 QuicPacketCount expected_cwnd = | 115 QuicPacketCount expected_cwnd = |
| 112 fix_convex_mode_ ? current_cwnd : current_cwnd + 1; | 116 fix_convex_mode_ ? current_cwnd : current_cwnd + 1; |
| 113 // Initialize the state. | 117 // Initialize the state. |
| 114 clock_.AdvanceTime(one_ms_); | 118 clock_.AdvanceTime(one_ms_); |
| 115 EXPECT_EQ(expected_cwnd, | 119 EXPECT_EQ(expected_cwnd, |
| 116 cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min)); | 120 cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min, |
| 121 clock_.ApproximateNow())); |
| 117 expected_cwnd = static_cast<QuicPacketCount>(current_cwnd * kNConnectionBeta); | 122 expected_cwnd = static_cast<QuicPacketCount>(current_cwnd * kNConnectionBeta); |
| 118 EXPECT_EQ(expected_cwnd, | 123 EXPECT_EQ(expected_cwnd, |
| 119 cubic_.CongestionWindowAfterPacketLoss(current_cwnd)); | 124 cubic_.CongestionWindowAfterPacketLoss(current_cwnd)); |
| 120 expected_cwnd = static_cast<QuicPacketCount>(current_cwnd * kNConnectionBeta); | 125 expected_cwnd = static_cast<QuicPacketCount>(current_cwnd * kNConnectionBeta); |
| 121 EXPECT_EQ(expected_cwnd, | 126 EXPECT_EQ(expected_cwnd, |
| 122 cubic_.CongestionWindowAfterPacketLoss(current_cwnd)); | 127 cubic_.CongestionWindowAfterPacketLoss(current_cwnd)); |
| 123 } | 128 } |
| 124 | 129 |
| 125 TEST_P(CubicTest, BelowOrigin) { | 130 TEST_P(CubicTest, BelowOrigin) { |
| 126 // Concave growth. | 131 // Concave growth. |
| 127 const QuicTime::Delta rtt_min = hundred_ms_; | 132 const QuicTime::Delta rtt_min = hundred_ms_; |
| 128 QuicPacketCount current_cwnd = 422; | 133 QuicPacketCount current_cwnd = 422; |
| 129 // Without the signed-integer, cubic-convex fix, we mistakenly | 134 // Without the signed-integer, cubic-convex fix, we mistakenly |
| 130 // increment cwnd after only one_ms_ and a single ack. | 135 // increment cwnd after only one_ms_ and a single ack. |
| 131 QuicPacketCount expected_cwnd = | 136 QuicPacketCount expected_cwnd = |
| 132 fix_convex_mode_ ? current_cwnd : current_cwnd + 1; | 137 fix_convex_mode_ ? current_cwnd : current_cwnd + 1; |
| 133 // Initialize the state. | 138 // Initialize the state. |
| 134 clock_.AdvanceTime(one_ms_); | 139 clock_.AdvanceTime(one_ms_); |
| 135 EXPECT_EQ(expected_cwnd, | 140 EXPECT_EQ(expected_cwnd, |
| 136 cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min)); | 141 cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min, |
| 142 clock_.ApproximateNow())); |
| 137 expected_cwnd = static_cast<QuicPacketCount>(current_cwnd * kNConnectionBeta); | 143 expected_cwnd = static_cast<QuicPacketCount>(current_cwnd * kNConnectionBeta); |
| 138 EXPECT_EQ(expected_cwnd, | 144 EXPECT_EQ(expected_cwnd, |
| 139 cubic_.CongestionWindowAfterPacketLoss(current_cwnd)); | 145 cubic_.CongestionWindowAfterPacketLoss(current_cwnd)); |
| 140 current_cwnd = expected_cwnd; | 146 current_cwnd = expected_cwnd; |
| 141 // First update after loss to initialize the epoch. | 147 // First update after loss to initialize the epoch. |
| 142 current_cwnd = cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min); | 148 current_cwnd = cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min, |
| 149 clock_.ApproximateNow()); |
| 143 // Cubic phase. | 150 // Cubic phase. |
| 144 for (int i = 0; i < 40; ++i) { | 151 for (int i = 0; i < 40; ++i) { |
| 145 clock_.AdvanceTime(hundred_ms_); | 152 clock_.AdvanceTime(hundred_ms_); |
| 146 current_cwnd = cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min); | 153 current_cwnd = cubic_.CongestionWindowAfterAck(current_cwnd, rtt_min, |
| 154 clock_.ApproximateNow()); |
| 147 } | 155 } |
| 148 expected_cwnd = 399; | 156 expected_cwnd = 399; |
| 149 EXPECT_EQ(expected_cwnd, current_cwnd); | 157 EXPECT_EQ(expected_cwnd, current_cwnd); |
| 150 } | 158 } |
| 151 | 159 |
| 152 } // namespace test | 160 } // namespace test |
| 153 } // namespace net | 161 } // namespace net |
| OLD | NEW |