OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/congestion_control/send_algorithm_simulator.h" | 5 #include "net/quic/congestion_control/send_algorithm_simulator.h" |
6 | 6 |
7 #include <limits> | 7 #include <limits> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/rand_util.h" | 10 #include "base/rand_util.h" |
11 #include "net/quic/crypto/quic_random.h" | 11 #include "net/quic/crypto/quic_random.h" |
12 | 12 |
13 using std::list; | 13 using std::list; |
14 using std::make_pair; | 14 using std::make_pair; |
15 using std::max; | 15 using std::max; |
16 using std::min; | 16 using std::min; |
17 using std::vector; | 17 using std::vector; |
18 | 18 |
19 namespace net { | 19 namespace net { |
20 | 20 |
21 namespace { | 21 namespace { |
22 | 22 |
23 const QuicByteCount kPacketSize = 1200; | 23 const QuicByteCount kPacketSize = 1200; |
24 | 24 |
25 } // namespace | 25 } // namespace |
26 | 26 |
27 SendAlgorithmSimulator::Sender::Sender(SendAlgorithmInterface* send_algorithm, | 27 SendAlgorithmSimulator::Sender::Sender(SendAlgorithmInterface* send_algorithm, |
28 RttStats* rtt_stats) | 28 RttStats* rtt_stats) |
| 29 : Sender(send_algorithm, rtt_stats, QuicTime::Delta::Zero()) {} |
| 30 |
| 31 SendAlgorithmSimulator::Sender::Sender(SendAlgorithmInterface* send_algorithm, |
| 32 RttStats* rtt_stats, |
| 33 QuicTime::Delta additional_rtt) |
29 : send_algorithm(send_algorithm), | 34 : send_algorithm(send_algorithm), |
30 rtt_stats(rtt_stats), | 35 rtt_stats(rtt_stats), |
| 36 additional_rtt(additional_rtt), |
31 last_sent(0), | 37 last_sent(0), |
32 last_acked(0), | 38 last_acked(0), |
33 next_acked(1), | 39 next_acked(1), |
34 max_cwnd(0), | 40 max_cwnd(0), |
35 min_cwnd(100000), | 41 min_cwnd(100000), |
36 max_cwnd_drop(0), | 42 max_cwnd_drop(0), |
37 last_cwnd(0), | 43 last_cwnd(0), |
38 last_transfer_bandwidth(QuicBandwidth::Zero()), | 44 last_transfer_bandwidth(QuicBandwidth::Zero()), |
39 last_transfer_loss_rate(0) {} | 45 last_transfer_loss_rate(0) {} |
40 | 46 |
| 47 SendAlgorithmSimulator::Transfer::Transfer(Sender* sender, |
| 48 QuicByteCount num_bytes, |
| 49 QuicTime start_time, |
| 50 string name) |
| 51 : sender(sender), |
| 52 num_bytes(num_bytes), |
| 53 bytes_acked(0), |
| 54 bytes_lost(0), |
| 55 bytes_in_flight(0), |
| 56 start_time(start_time), |
| 57 name(name) {} |
| 58 |
41 SendAlgorithmSimulator::SendAlgorithmSimulator( | 59 SendAlgorithmSimulator::SendAlgorithmSimulator( |
42 MockClock* clock, | 60 MockClock* clock, |
43 QuicBandwidth bandwidth, | 61 QuicBandwidth bandwidth, |
44 QuicTime::Delta rtt) | 62 QuicTime::Delta rtt) |
45 : clock_(clock), | 63 : clock_(clock), |
46 lose_next_ack_(false), | 64 lose_next_ack_(false), |
47 forward_loss_rate_(0), | 65 forward_loss_rate_(0), |
48 reverse_loss_rate_(0), | 66 reverse_loss_rate_(0), |
49 loss_correlation_(0), | 67 loss_correlation_(0), |
50 bandwidth_(bandwidth), | 68 bandwidth_(bandwidth), |
51 rtt_(rtt), | 69 rtt_(rtt), |
52 buffer_size_(1000000), | 70 buffer_size_(1000000), |
53 delayed_ack_timer_(QuicTime::Delta::FromMilliseconds(100)) { | 71 delayed_ack_timer_(QuicTime::Delta::FromMilliseconds(100)) { |
54 uint32 seed = base::RandInt(0, std::numeric_limits<int32>::max()); | 72 uint32 seed = base::RandInt(0, std::numeric_limits<int32>::max()); |
55 DVLOG(1) << "Seeding SendAlgorithmSimulator with " << seed; | 73 DVLOG(1) << "Seeding SendAlgorithmSimulator with " << seed; |
56 simple_random_.set_seed(seed); | 74 simple_random_.set_seed(seed); |
57 } | 75 } |
58 | 76 |
59 SendAlgorithmSimulator::~SendAlgorithmSimulator() {} | 77 SendAlgorithmSimulator::~SendAlgorithmSimulator() {} |
60 | 78 |
61 void SendAlgorithmSimulator::AddTransfer(Sender* sender, size_t num_bytes) { | 79 void SendAlgorithmSimulator::AddTransfer(Sender* sender, size_t num_bytes) { |
62 AddTransfer(sender, num_bytes, clock_->Now()); | 80 AddTransfer(sender, num_bytes, clock_->Now(), |
| 81 StringPrintf("#%zu", pending_transfers_.size())); |
63 } | 82 } |
64 | 83 |
65 void SendAlgorithmSimulator::AddTransfer( | 84 void SendAlgorithmSimulator::AddTransfer( |
66 Sender* sender, size_t num_bytes, QuicTime start_time) { | 85 Sender* sender, size_t num_bytes, QuicTime start_time, string name) { |
67 pending_transfers_.push_back(Transfer(sender, num_bytes, start_time)); | 86 pending_transfers_.push_back(Transfer(sender, num_bytes, start_time, name)); |
68 // Record initial stats from when the transfer begins. | 87 // Record initial stats from when the transfer begins. |
69 pending_transfers_.back().sender->RecordStats(); | 88 pending_transfers_.back().sender->RecordStats(); |
70 } | 89 } |
71 | 90 |
72 void SendAlgorithmSimulator::TransferBytes() { | 91 void SendAlgorithmSimulator::TransferBytes() { |
73 TransferBytes(kuint64max, QuicTime::Delta::Infinite()); | 92 TransferBytes(kuint64max, QuicTime::Delta::Infinite()); |
74 } | 93 } |
75 | 94 |
76 void SendAlgorithmSimulator::TransferBytes(QuicByteCount max_bytes, | 95 void SendAlgorithmSimulator::TransferBytes(QuicByteCount max_bytes, |
77 QuicTime::Delta max_time) { | 96 QuicTime::Delta max_time) { |
(...skipping 17 matching lines...) Expand all Loading... |
95 SendDataNow(&pending_transfers_.front()); | 114 SendDataNow(&pending_transfers_.front()); |
96 } else if (ack_event.time_delta < send_event.time_delta) { | 115 } else if (ack_event.time_delta < send_event.time_delta) { |
97 DVLOG(1) << "Handling ack of largest observed:" | 116 DVLOG(1) << "Handling ack of largest observed:" |
98 << ack_event.transfer->sender->next_acked << ", advancing time:" | 117 << ack_event.transfer->sender->next_acked << ", advancing time:" |
99 << ack_event.time_delta.ToMicroseconds() << "us"; | 118 << ack_event.time_delta.ToMicroseconds() << "us"; |
100 // Ack data all the data up to ack time and lose any missing sequence | 119 // Ack data all the data up to ack time and lose any missing sequence |
101 // numbers. | 120 // numbers. |
102 clock_->AdvanceTime(ack_event.time_delta); | 121 clock_->AdvanceTime(ack_event.time_delta); |
103 HandlePendingAck(ack_event.transfer); | 122 HandlePendingAck(ack_event.transfer); |
104 } else { | 123 } else { |
105 DVLOG(1) << "Sending, advancing time:" | 124 DVLOG(1) << "Sending transfer '" << send_event.transfer->name |
106 << send_event.time_delta.ToMicroseconds() << "us"; | 125 << "', advancing time:" << send_event.time_delta.ToMicroseconds() |
| 126 << "us"; |
107 clock_->AdvanceTime(send_event.time_delta); | 127 clock_->AdvanceTime(send_event.time_delta); |
108 SendDataNow(send_event.transfer); | 128 SendDataNow(send_event.transfer); |
109 bytes_sent += kPacketSize; | 129 bytes_sent += kPacketSize; |
110 } | 130 } |
111 } | 131 } |
112 } | 132 } |
113 | 133 |
114 SendAlgorithmSimulator::PacketEvent SendAlgorithmSimulator::NextSendEvent() { | 134 SendAlgorithmSimulator::PacketEvent SendAlgorithmSimulator::NextSendEvent() { |
115 QuicTime::Delta next_send_time = QuicTime::Delta::Infinite(); | 135 QuicTime::Delta next_send_time = QuicTime::Delta::Infinite(); |
116 Transfer* transfer = nullptr; | 136 Transfer* transfer = nullptr; |
117 for (vector<Transfer>::iterator it = pending_transfers_.begin(); | 137 for (vector<Transfer>::iterator it = pending_transfers_.begin(); |
118 it != pending_transfers_.end(); ++it) { | 138 it != pending_transfers_.end(); ++it) { |
119 // If we've already sent enough bytes, wait for them to be acked. | 139 // If we've already sent enough bytes, wait for them to be acked. |
120 if (it->bytes_acked + it->bytes_in_flight >= it->num_bytes) { | 140 if (it->bytes_acked + it->bytes_in_flight >= it->num_bytes) { |
121 continue; | 141 continue; |
122 } | 142 } |
123 // If the flow hasn't started, use the start time. | 143 // If the flow hasn't started, use the start time. |
124 QuicTime::Delta transfer_send_time = it->start_time.Subtract(clock_->Now()); | 144 QuicTime::Delta transfer_send_time = it->start_time.Subtract(clock_->Now()); |
125 if (clock_->Now() >= it->start_time) { | 145 if (clock_->Now() >= it->start_time) { |
126 transfer_send_time = | 146 transfer_send_time = |
127 it->sender->send_algorithm->TimeUntilSend( | 147 it->sender->send_algorithm->TimeUntilSend( |
128 clock_->Now(), it->bytes_in_flight, HAS_RETRANSMITTABLE_DATA); | 148 clock_->Now(), it->bytes_in_flight, HAS_RETRANSMITTABLE_DATA); |
129 } | 149 } |
130 if (transfer_send_time < next_send_time) { | 150 if (transfer_send_time < next_send_time) { |
131 next_send_time = transfer_send_time; | 151 next_send_time = transfer_send_time; |
132 transfer = &(*it); | 152 transfer = &(*it); |
133 } | 153 } |
134 } | 154 } |
135 DVLOG(1) << "NextSendTime returning delta(ms):" | 155 DVLOG(1) << "NextSendTime returning delta(ms):" |
136 << next_send_time.ToMilliseconds(); | 156 << next_send_time.ToMilliseconds() << ", transfer '" |
| 157 << transfer->name; |
137 return PacketEvent(next_send_time, transfer); | 158 return PacketEvent(next_send_time, transfer); |
138 } | 159 } |
139 | 160 |
140 // NextAck takes into account packet loss in both forward and reverse | 161 // NextAck takes into account packet loss in both forward and reverse |
141 // direction, as well as correlated losses. And it assumes the receiver acks | 162 // direction, as well as correlated losses. And it assumes the receiver acks |
142 // every other packet when there is no loss. | 163 // every other packet when there is no loss. |
143 SendAlgorithmSimulator::PacketEvent SendAlgorithmSimulator::NextAckEvent() { | 164 SendAlgorithmSimulator::PacketEvent SendAlgorithmSimulator::NextAckEvent() { |
144 if (sent_packets_.empty()) { | 165 if (sent_packets_.empty()) { |
145 DVLOG(1) << "No outstanding packets to ack for any transfer."; | 166 DVLOG(1) << "No outstanding packets to ack for any transfer."; |
146 return PacketEvent(QuicTime::Delta::Infinite(), nullptr); | 167 return PacketEvent(QuicTime::Delta::Infinite(), nullptr); |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
206 } | 227 } |
207 *next_acked = it->sequence_number; | 228 *next_acked = it->sequence_number; |
208 ack_delay = it->ack_time.Subtract(clock_->Now()); | 229 ack_delay = it->ack_time.Subtract(clock_->Now()); |
209 if (HasRecentLostPackets(transfer, *next_acked) || | 230 if (HasRecentLostPackets(transfer, *next_acked) || |
210 (*next_acked - last_acked) >= 2) { | 231 (*next_acked - last_acked) >= 2) { |
211 break; | 232 break; |
212 } | 233 } |
213 ack_delay = ack_delay.Add(delayed_ack_timer_); | 234 ack_delay = ack_delay.Add(delayed_ack_timer_); |
214 } | 235 } |
215 | 236 |
216 DVLOG(1) << "FindNextAcked found next_acked_:" | 237 DVLOG(1) << "FindNextAck found next_acked_:" << transfer->sender->next_acked |
217 << transfer->sender->next_acked | |
218 << " last_acked:" << transfer->sender->last_acked | 238 << " last_acked:" << transfer->sender->last_acked |
219 << " ack_delay(ms):" << ack_delay.ToMilliseconds(); | 239 << " ack_time(ms):" << ack_delay.ToMilliseconds(); |
220 return ack_delay; | 240 return ack_delay; |
221 } | 241 } |
222 | 242 |
223 bool SendAlgorithmSimulator::HasRecentLostPackets( | 243 bool SendAlgorithmSimulator::HasRecentLostPackets( |
224 const Transfer* transfer, QuicPacketSequenceNumber next_acked) const { | 244 const Transfer* transfer, QuicPacketSequenceNumber next_acked) const { |
225 QuicPacketSequenceNumber last_packet = transfer->sender->last_acked; | 245 QuicPacketSequenceNumber last_packet = transfer->sender->last_acked; |
226 for (list<SentPacket>::const_iterator it = sent_packets_.begin(); | 246 for (list<SentPacket>::const_iterator it = sent_packets_.begin(); |
227 it != sent_packets_.end() && it->sequence_number < next_acked; ++it) { | 247 it != sent_packets_.end() && it->sequence_number < next_acked; ++it) { |
228 if (transfer != it->transfer) { | 248 if (transfer != it->transfer) { |
229 continue; | 249 continue; |
(...skipping 11 matching lines...) Expand all Loading... |
241 } | 261 } |
242 return false; | 262 return false; |
243 } | 263 } |
244 | 264 |
245 void SendAlgorithmSimulator::HandlePendingAck(Transfer* transfer) { | 265 void SendAlgorithmSimulator::HandlePendingAck(Transfer* transfer) { |
246 Sender* sender = transfer->sender; | 266 Sender* sender = transfer->sender; |
247 DCHECK_LT(sender->last_acked, sender->next_acked); | 267 DCHECK_LT(sender->last_acked, sender->next_acked); |
248 SendAlgorithmInterface::CongestionVector acked_packets; | 268 SendAlgorithmInterface::CongestionVector acked_packets; |
249 SendAlgorithmInterface::CongestionVector lost_packets; | 269 SendAlgorithmInterface::CongestionVector lost_packets; |
250 DVLOG(1) << "Acking packets from:" << sender->last_acked | 270 DVLOG(1) << "Acking packets from:" << sender->last_acked |
251 << " to " << sender->next_acked | 271 << " to " << sender->next_acked |
252 << " bytes_in_flight:" << transfer->bytes_in_flight | 272 << " bytes_in_flight:" << transfer->bytes_in_flight |
253 << " Now():" << (clock_->Now().ToDebuggingValue() / 1000) << "ms"; | 273 << " Now():" << (clock_->Now().ToDebuggingValue() / 1000) << "ms"; |
254 // Some entries may be missing from the sent_packets_ array, if they were | 274 // Some entries may be missing from the sent_packets_ array, if they were |
255 // dropped due to buffer overruns. | 275 // dropped due to buffer overruns. |
256 SentPacket largest_observed; | 276 SentPacket largest_observed; |
257 list<SentPacket>::iterator it = sent_packets_.begin(); | 277 list<SentPacket>::iterator it = sent_packets_.begin(); |
258 while (sender->last_acked < sender->next_acked) { | 278 while (sender->last_acked < sender->next_acked) { |
259 ++sender->last_acked; | 279 ++sender->last_acked; |
260 TransmissionInfo info = TransmissionInfo(); | 280 TransmissionInfo info = TransmissionInfo(); |
261 info.bytes_sent = kPacketSize; | 281 info.bytes_sent = kPacketSize; |
262 info.in_flight = true; | 282 info.in_flight = true; |
263 // Find the next SentPacket for this transfer. | 283 // Find the next SentPacket for this transfer. |
(...skipping 11 matching lines...) Expand all Loading... |
275 if (it->lost) { | 295 if (it->lost) { |
276 lost_packets.push_back(make_pair(sender->last_acked, info)); | 296 lost_packets.push_back(make_pair(sender->last_acked, info)); |
277 } else { | 297 } else { |
278 acked_packets.push_back(make_pair(sender->last_acked, info)); | 298 acked_packets.push_back(make_pair(sender->last_acked, info)); |
279 } | 299 } |
280 // This packet has been acked or lost, remove it from sent_packets_. | 300 // This packet has been acked or lost, remove it from sent_packets_. |
281 largest_observed = *it; | 301 largest_observed = *it; |
282 sent_packets_.erase(it++); | 302 sent_packets_.erase(it++); |
283 } | 303 } |
284 | 304 |
285 DCHECK(largest_observed.ack_time.IsInitialized()); | 305 DCHECK(!largest_observed.lost); |
286 DVLOG(1) << "Updating RTT from send_time:" | 306 DVLOG(1) << "Updating RTT from send_time:" |
287 << largest_observed.send_time.ToDebuggingValue() << " to ack_time:" | 307 << largest_observed.send_time.ToDebuggingValue() << " to ack_time:" |
288 << largest_observed.ack_time.ToDebuggingValue(); | 308 << largest_observed.ack_time.ToDebuggingValue(); |
289 QuicTime::Delta measured_rtt = | 309 QuicTime::Delta measured_rtt = |
290 largest_observed.ack_time.Subtract(largest_observed.send_time); | 310 largest_observed.ack_time.Subtract(largest_observed.send_time); |
291 DCHECK_GE(measured_rtt.ToMicroseconds(), rtt_.ToMicroseconds()); | 311 DCHECK_GE(measured_rtt.ToMicroseconds(), rtt_.ToMicroseconds()); |
292 sender->rtt_stats->UpdateRtt(measured_rtt, | 312 sender->rtt_stats->UpdateRtt(measured_rtt, |
293 QuicTime::Delta::Zero(), | 313 QuicTime::Delta::Zero(), |
294 clock_->Now()); | 314 clock_->Now()); |
295 sender->send_algorithm->OnCongestionEvent( | 315 sender->send_algorithm->OnCongestionEvent( |
(...skipping 24 matching lines...) Expand all Loading... |
320 break; | 340 break; |
321 } | 341 } |
322 } | 342 } |
323 } | 343 } |
324 } | 344 } |
325 | 345 |
326 void SendAlgorithmSimulator::SendDataNow(Transfer* transfer) { | 346 void SendAlgorithmSimulator::SendDataNow(Transfer* transfer) { |
327 Sender* sender = transfer->sender; | 347 Sender* sender = transfer->sender; |
328 ++sender->last_sent; | 348 ++sender->last_sent; |
329 DVLOG(1) << "Sending packet:" << sender->last_sent | 349 DVLOG(1) << "Sending packet:" << sender->last_sent |
| 350 << " name:" << transfer->name |
330 << " bytes_in_flight:" << transfer->bytes_in_flight | 351 << " bytes_in_flight:" << transfer->bytes_in_flight |
| 352 << " cwnd:" << sender->send_algorithm->GetCongestionWindow() |
331 << " Now():" << (clock_->Now().ToDebuggingValue() / 1000) << "ms"; | 353 << " Now():" << (clock_->Now().ToDebuggingValue() / 1000) << "ms"; |
332 sender->send_algorithm->OnPacketSent( | 354 sender->send_algorithm->OnPacketSent( |
333 clock_->Now(), transfer->bytes_in_flight, | 355 clock_->Now(), transfer->bytes_in_flight, |
334 sender->last_sent, kPacketSize, HAS_RETRANSMITTABLE_DATA); | 356 sender->last_sent, kPacketSize, HAS_RETRANSMITTABLE_DATA); |
335 // Lose the packet immediately if the buffer is full. | 357 // Lose the packet immediately if the buffer is full. |
336 if (sent_packets_.size() * kPacketSize < buffer_size_) { | 358 if (sent_packets_.size() * kPacketSize < buffer_size_) { |
337 // TODO(ianswett): This buffer simulation is an approximation. | 359 // TODO(ianswett): This buffer simulation is an approximation. |
338 // An ack time of zero means loss. | 360 // An ack time of zero means loss. |
339 bool packet_lost = | 361 bool packet_lost = |
340 forward_loss_rate_ * kuint64max > simple_random_.RandUint64(); | 362 forward_loss_rate_ * kuint64max > simple_random_.RandUint64(); |
341 // Handle correlated loss. | 363 // Handle correlated loss. |
342 if (!sent_packets_.empty() && sent_packets_.back().lost && | 364 if (!sent_packets_.empty() && sent_packets_.back().lost && |
343 loss_correlation_ * kuint64max > simple_random_.RandUint64()) { | 365 loss_correlation_ * kuint64max > simple_random_.RandUint64()) { |
344 packet_lost = true; | 366 packet_lost = true; |
345 } | 367 } |
346 DVLOG(1) << "losing packet:" << sender->last_sent | 368 DVLOG(1) << "losing packet:" << sender->last_sent |
347 << " due to random loss."; | 369 << " name:" << transfer->name << " due to random loss."; |
348 | 370 |
349 // If the number of bytes in flight are less than the bdp, there's | 371 // If the number of bytes in flight are less than the bdp, there's |
350 // no buffering delay. Bytes lost from the buffer are not counted. | 372 // no buffering delay. Bytes lost from the buffer are not counted. |
351 QuicByteCount bdp = bandwidth_.ToBytesPerPeriod(rtt_); | 373 QuicByteCount bdp = bandwidth_.ToBytesPerPeriod(rtt_); |
352 QuicTime ack_time = clock_->Now().Add(rtt_); | 374 QuicTime ack_time = clock_->Now().Add(rtt_).Add(sender->additional_rtt); |
353 if (kPacketSize > bdp) { | 375 if (kPacketSize > bdp) { |
354 ack_time = ack_time.Add(bandwidth_.TransferTime(kPacketSize - bdp)); | 376 ack_time = ack_time.Add(bandwidth_.TransferTime(kPacketSize - bdp)); |
355 } | 377 } |
356 QuicTime queue_ack_time = sent_packets_.empty() ? QuicTime::Zero() : | 378 QuicTime queue_ack_time = sent_packets_.empty() ? QuicTime::Zero() : |
357 sent_packets_.back().ack_time.Add(bandwidth_.TransferTime(kPacketSize)); | 379 sent_packets_.back().ack_time.Add(bandwidth_.TransferTime(kPacketSize)); |
358 ack_time = QuicTime::Max(ack_time, queue_ack_time); | 380 ack_time = QuicTime::Max(ack_time, queue_ack_time); |
359 sent_packets_.push_back(SentPacket( | 381 sent_packets_.push_back(SentPacket( |
360 sender->last_sent, clock_->Now(), ack_time, packet_lost, transfer)); | 382 sender->last_sent, clock_->Now(), ack_time, packet_lost, transfer)); |
361 } else { | 383 } else { |
362 DVLOG(1) << "losing packet:" << sender->last_sent | 384 DVLOG(1) << "losing packet:" << sender->last_sent |
363 << " because the buffer was full."; | 385 << " name:" << transfer->name << " because the buffer was full."; |
364 } | 386 } |
365 transfer->bytes_in_flight += kPacketSize; | 387 transfer->bytes_in_flight += kPacketSize; |
366 } | 388 } |
367 | 389 |
368 // Advance the time by |delta| without sending anything. | 390 // Advance the time by |delta| without sending anything. |
369 void SendAlgorithmSimulator::AdvanceTime(QuicTime::Delta delta) { | 391 void SendAlgorithmSimulator::AdvanceTime(QuicTime::Delta delta) { |
370 clock_->AdvanceTime(delta); | 392 clock_->AdvanceTime(delta); |
371 } | 393 } |
372 | 394 |
373 } // namespace net | 395 } // namespace net |
OLD | NEW |