OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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/bandwidth_sampler.h" | 5 #include "net/quic/core/congestion_control/bandwidth_sampler.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "net/quic/platform/api/quic_bug_tracker.h" | 9 #include "net/quic/platform/api/quic_bug_tracker.h" |
| 10 #include "net/quic/platform/api/quic_flag_utils.h" |
| 11 #include "net/quic/platform/api/quic_flags.h" |
10 | 12 |
11 namespace net { | 13 namespace net { |
12 BandwidthSampler::BandwidthSampler() | 14 BandwidthSampler::BandwidthSampler() |
13 : total_bytes_sent_(0), | 15 : total_bytes_sent_(0), |
14 total_bytes_acked_(0), | 16 total_bytes_acked_(0), |
15 total_bytes_sent_at_last_acked_packet_(0), | 17 total_bytes_sent_at_last_acked_packet_(0), |
16 last_acked_packet_sent_time_(QuicTime::Zero()), | 18 last_acked_packet_sent_time_(QuicTime::Zero()), |
17 last_acked_packet_ack_time_(QuicTime::Zero()), | 19 last_acked_packet_ack_time_(QuicTime::Zero()), |
18 last_sent_packet_(0), | 20 last_sent_packet_(0), |
19 is_app_limited_(false), | 21 is_app_limited_(false), |
20 end_of_app_limited_phase_(0), | 22 end_of_app_limited_phase_(0), |
21 connection_state_map_() {} | 23 connection_state_map_(), |
| 24 connection_state_map_new_(), |
| 25 use_new_connection_state_map_( |
| 26 FLAGS_quic_reloadable_flag_quic_faster_bandwidth_sampler) {} |
22 | 27 |
23 BandwidthSampler::~BandwidthSampler() {} | 28 BandwidthSampler::~BandwidthSampler() {} |
24 | 29 |
25 void BandwidthSampler::OnPacketSent( | 30 void BandwidthSampler::OnPacketSent( |
26 QuicTime sent_time, | 31 QuicTime sent_time, |
27 QuicPacketNumber packet_number, | 32 QuicPacketNumber packet_number, |
28 QuicByteCount bytes, | 33 QuicByteCount bytes, |
29 QuicByteCount bytes_in_flight, | 34 QuicByteCount bytes_in_flight, |
30 HasRetransmittableData has_retransmittable_data) { | 35 HasRetransmittableData has_retransmittable_data) { |
31 last_sent_packet_ = packet_number; | 36 last_sent_packet_ = packet_number; |
(...skipping 12 matching lines...) Expand all Loading... |
44 // importantly at the beginning of the connection. | 49 // importantly at the beginning of the connection. |
45 if (bytes_in_flight == 0) { | 50 if (bytes_in_flight == 0) { |
46 last_acked_packet_ack_time_ = sent_time; | 51 last_acked_packet_ack_time_ = sent_time; |
47 total_bytes_sent_at_last_acked_packet_ = total_bytes_sent_; | 52 total_bytes_sent_at_last_acked_packet_ = total_bytes_sent_; |
48 | 53 |
49 // In this situation ack compression is not a concern, set send rate to | 54 // In this situation ack compression is not a concern, set send rate to |
50 // effectively infinite. | 55 // effectively infinite. |
51 last_acked_packet_sent_time_ = sent_time; | 56 last_acked_packet_sent_time_ = sent_time; |
52 } | 57 } |
53 | 58 |
| 59 if (use_new_connection_state_map_) { |
| 60 if (!connection_state_map_new_.IsEmpty() && |
| 61 packet_number > |
| 62 connection_state_map_new_.last_packet() + kMaxTrackedPackets) { |
| 63 QUIC_BUG << "BandwidthSampler in-flight packet map has exceeded maximum " |
| 64 "number " |
| 65 "of tracked packets."; |
| 66 } |
| 67 |
| 68 bool success = connection_state_map_new_.Emplace(packet_number, sent_time, |
| 69 bytes, *this); |
| 70 QUIC_BUG_IF(!success) << "BandwidthSampler failed to insert the packet " |
| 71 "into the map, most likely because it's already " |
| 72 "in it."; |
| 73 return; |
| 74 } |
| 75 |
54 DCHECK(connection_state_map_.find(packet_number) == | 76 DCHECK(connection_state_map_.find(packet_number) == |
55 connection_state_map_.end()); | 77 connection_state_map_.end()); |
56 connection_state_map_.emplace( | 78 connection_state_map_.emplace( |
57 packet_number, ConnectionStateOnSentPacket(sent_time, bytes, *this)); | 79 packet_number, ConnectionStateOnSentPacket(sent_time, bytes, *this)); |
58 | 80 |
59 QUIC_BUG_IF(connection_state_map_.size() > kMaxTrackedPackets) | 81 QUIC_BUG_IF(connection_state_map_.size() > kMaxTrackedPackets) |
60 << "BandwidthSampler in-flight packet map has exceeded maximum number " | 82 << "BandwidthSampler in-flight packet map has exceeded maximum number " |
61 "of tracked packets."; | 83 "of tracked packets."; |
62 } | 84 } |
63 | 85 |
64 BandwidthSample BandwidthSampler::OnPacketAcknowledged( | 86 BandwidthSample BandwidthSampler::OnPacketAcknowledged( |
65 QuicTime ack_time, | 87 QuicTime ack_time, |
66 QuicPacketNumber packet_number) { | 88 QuicPacketNumber packet_number) { |
| 89 if (use_new_connection_state_map_) { |
| 90 ConnectionStateOnSentPacket* sent_packet_pointer = |
| 91 connection_state_map_new_.GetEntry(packet_number); |
| 92 if (sent_packet_pointer == nullptr) { |
| 93 // See the TODO below. |
| 94 return BandwidthSample(); |
| 95 } |
| 96 BandwidthSample sample = OnPacketAcknowledgedInner(ack_time, packet_number, |
| 97 *sent_packet_pointer); |
| 98 connection_state_map_new_.Remove(packet_number); |
| 99 QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_faster_bandwidth_sampler, 1, 2); |
| 100 return sample; |
| 101 } |
| 102 |
67 auto it = connection_state_map_.find(packet_number); | 103 auto it = connection_state_map_.find(packet_number); |
68 if (it == connection_state_map_.end()) { | 104 if (it == connection_state_map_.end()) { |
69 // TODO(vasilvv): currently, this can happen because the congestion | 105 // TODO(vasilvv): currently, this can happen because the congestion |
70 // controller can be created while some of the handshake packets are still | 106 // controller can be created while some of the handshake packets are still |
71 // in flight. Once the sampler is fully integrated with unacked packet map, | 107 // in flight. Once the sampler is fully integrated with unacked packet map, |
72 // this should be a QUIC_BUG equivalent. | 108 // this should be a QUIC_BUG equivalent. |
73 return BandwidthSample(); | 109 return BandwidthSample(); |
74 } | 110 } |
75 const ConnectionStateOnSentPacket sent_packet = it->second; | 111 BandwidthSample sample = |
| 112 OnPacketAcknowledgedInner(ack_time, packet_number, it->second); |
| 113 connection_state_map_.erase(it); |
| 114 return sample; |
| 115 } |
76 | 116 |
| 117 BandwidthSample BandwidthSampler::OnPacketAcknowledgedInner( |
| 118 QuicTime ack_time, |
| 119 QuicPacketNumber packet_number, |
| 120 const ConnectionStateOnSentPacket& sent_packet) { |
77 total_bytes_acked_ += sent_packet.size; | 121 total_bytes_acked_ += sent_packet.size; |
78 total_bytes_sent_at_last_acked_packet_ = sent_packet.total_bytes_sent; | 122 total_bytes_sent_at_last_acked_packet_ = sent_packet.total_bytes_sent; |
79 last_acked_packet_sent_time_ = sent_packet.sent_time; | 123 last_acked_packet_sent_time_ = sent_packet.sent_time; |
80 last_acked_packet_ack_time_ = ack_time; | 124 last_acked_packet_ack_time_ = ack_time; |
81 | 125 |
82 connection_state_map_.erase(it); | |
83 | |
84 // Exit app-limited phase once a packet that was sent while the connection is | 126 // Exit app-limited phase once a packet that was sent while the connection is |
85 // not app-limited is acknowledged. | 127 // not app-limited is acknowledged. |
86 if (is_app_limited_ && packet_number > end_of_app_limited_phase_) { | 128 if (is_app_limited_ && packet_number > end_of_app_limited_phase_) { |
87 is_app_limited_ = false; | 129 is_app_limited_ = false; |
88 } | 130 } |
89 | 131 |
90 // There might have been no packets acknowledged at the moment when the | 132 // There might have been no packets acknowledged at the moment when the |
91 // current packet was sent. In that case, there is no bandwidth sample to | 133 // current packet was sent. In that case, there is no bandwidth sample to |
92 // make. | 134 // make. |
93 if (sent_packet.last_acked_packet_sent_time == QuicTime::Zero()) { | 135 if (sent_packet.last_acked_packet_sent_time == QuicTime::Zero()) { |
(...skipping 29 matching lines...) Expand all Loading... |
123 // means that the RTT measurements here can be artificially high, especially | 165 // means that the RTT measurements here can be artificially high, especially |
124 // on low bandwidth connections. | 166 // on low bandwidth connections. |
125 sample.rtt = ack_time - sent_packet.sent_time; | 167 sample.rtt = ack_time - sent_packet.sent_time; |
126 // A sample is app-limited if the packet was sent during the app-limited | 168 // A sample is app-limited if the packet was sent during the app-limited |
127 // phase. | 169 // phase. |
128 sample.is_app_limited = sent_packet.is_app_limited; | 170 sample.is_app_limited = sent_packet.is_app_limited; |
129 return sample; | 171 return sample; |
130 } | 172 } |
131 | 173 |
132 void BandwidthSampler::OnPacketLost(QuicPacketNumber packet_number) { | 174 void BandwidthSampler::OnPacketLost(QuicPacketNumber packet_number) { |
| 175 if (use_new_connection_state_map_) { |
| 176 // TODO(vasilvv): see the comment for the case of missing packets in |
| 177 // BandwidthSampler::OnPacketAcknowledged on why this does not raise a |
| 178 // QUIC_BUG when removal fails. |
| 179 connection_state_map_new_.Remove(packet_number); |
| 180 QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_faster_bandwidth_sampler, 2, 2); |
| 181 return; |
| 182 } |
| 183 |
133 auto it = connection_state_map_.find(packet_number); | 184 auto it = connection_state_map_.find(packet_number); |
134 if (it == connection_state_map_.end()) { | 185 if (it == connection_state_map_.end()) { |
135 // TODO(vasilvv): see the comment for the same case in | 186 // TODO(vasilvv): see the comment for the same case in |
136 // BandwidthSampler::OnPacketAcknowledged. | 187 // BandwidthSampler::OnPacketAcknowledged. |
137 return; | 188 return; |
138 } | 189 } |
139 | 190 |
140 connection_state_map_.erase(it); | 191 connection_state_map_.erase(it); |
141 } | 192 } |
142 | 193 |
143 void BandwidthSampler::OnAppLimited() { | 194 void BandwidthSampler::OnAppLimited() { |
144 is_app_limited_ = true; | 195 is_app_limited_ = true; |
145 end_of_app_limited_phase_ = last_sent_packet_; | 196 end_of_app_limited_phase_ = last_sent_packet_; |
146 } | 197 } |
147 | 198 |
148 void BandwidthSampler::RemoveObsoletePackets(QuicPacketNumber least_unacked) { | 199 void BandwidthSampler::RemoveObsoletePackets(QuicPacketNumber least_unacked) { |
| 200 if (use_new_connection_state_map_) { |
| 201 while (!connection_state_map_new_.IsEmpty() && |
| 202 connection_state_map_new_.first_packet() < least_unacked) { |
| 203 connection_state_map_new_.Remove( |
| 204 connection_state_map_new_.first_packet()); |
| 205 } |
| 206 return; |
| 207 } |
149 while (!connection_state_map_.empty() && | 208 while (!connection_state_map_.empty() && |
150 connection_state_map_.begin()->first < least_unacked) { | 209 connection_state_map_.begin()->first < least_unacked) { |
151 connection_state_map_.pop_front(); | 210 connection_state_map_.pop_front(); |
152 } | 211 } |
153 } | 212 } |
154 | 213 |
155 } // namespace net | 214 } // namespace net |
OLD | NEW |