1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
7 #include "net/curvecp/rtt_and_send_rate_calculator.h"
11 RttAndSendRateCalculator::RttAndSendRateCalculator()
17 rtt_timeout_(base::Time::kMicrosecondsPerSecond
),
19 rtt_seenrecenthigh_(0),
20 rtt_seenrecentlow_(0),
21 rtt_seenolderhigh_(0),
26 void RttAndSendRateCalculator::OnMessage(int32 rtt_us
) {
31 void RttAndSendRateCalculator::OnTimeout() {
32 base::TimeDelta time_since_last_loss
= last_sample_time_
- last_loss_time_
;
33 if (time_since_last_loss
.InMilliseconds() < 4 * rtt_timeout_
)
36 last_loss_time_
= last_sample_time_
;
37 last_edge_time_
= last_sample_time_
;
41 void RttAndSendRateCalculator::UpdateRTT(int32 rtt_us
) {
43 last_sample_time_
= base::TimeTicks::Now();
45 // Initialize for the first sample.
47 rtt_average_
= rtt_latest_
;
48 rtt_deviation_
= rtt_latest_
;
49 rtt_highwater_
= rtt_latest_
;
50 rtt_lowwater_
= rtt_latest_
;
53 // Jacobson's retransmission timeout calculation.
54 int32 rtt_delta
= rtt_latest_
- rtt_average_
;
55 rtt_average_
+= rtt_delta
/ 8;
57 rtt_delta
= -rtt_delta
;
58 rtt_delta
-= rtt_deviation_
;
59 rtt_deviation_
+= rtt_delta
/ 4;
60 rtt_timeout_
= rtt_average_
+ (4 * rtt_deviation_
);
62 // Adjust for delayed acks with anti-spiking.
63 // TODO(mbelshe): this seems high.
64 rtt_timeout_
+= 8 * send_rate_
;
66 // Recognize the top and bottom of the congestion cycle.
67 rtt_delta
= rtt_latest_
- rtt_highwater_
;
68 rtt_highwater_
+= rtt_delta
/ 1024;
70 rtt_delta
= rtt_latest_
- rtt_lowwater_
;
72 rtt_lowwater_
+= rtt_delta
/ 8192;
74 rtt_lowwater_
+= rtt_delta
/ 256;
77 void RttAndSendRateCalculator::AdjustSendRate() {
78 last_sample_time_
= base::TimeTicks::Now();
80 base::TimeDelta time
= last_sample_time_
- last_send_adjust_time_
;
82 // We only adjust the send rate approximately every 16 samples.
83 if (time
.InMicroseconds() < 16 * send_rate_
)
87 rtt_highwater_
+ (5 * base::Time::kMicrosecondsPerMillisecond
))
88 rtt_seenrecenthigh_
= true;
89 else if (rtt_average_
< rtt_lowwater_
)
90 rtt_seenrecentlow_
= true;
92 last_send_adjust_time_
= last_sample_time_
;
94 // If too much time has elapsed, re-initialize the send_rate.
95 if (time
.InMicroseconds() > 10 * base::Time::kMicrosecondsPerSecond
) {
96 send_rate_
= base::Time::kMicrosecondsPerSecond
; // restart.
97 send_rate_
+= randommod(send_rate_
/ 8);
100 // TODO(mbelshe): Why is 128us a lower bound?
101 if (send_rate_
>= 128) {
102 // Additive increase: adjust 1/N by a constant c.
103 // rtt-fair additive increase: adjust 1/N by a constant c every nanosec.
104 // approximation: adjust 1/N by cN every N nanoseconds.
106 // TODO(mbelshe): he used c == 2^-51. for nanosecs.
107 // I use c == 2^31, for microsecs.
109 // i.e. N <- 1/(1/N + cN) = N/(1 + cN^2) every N nanosec.
110 if (false && send_rate_
< 16384) {
111 // N/(1+cN^2) approx N - cN^3
112 // TODO(mbelshe): note that he is using (cN)^3 here, not what he wrote.
113 int32 msec
= send_rate_
/ 128;
114 send_rate_
-= msec
* msec
* msec
;
116 double d
= send_rate_
;
117 send_rate_
= d
/ (1 + d
* d
/ 2147483648.0); // 2^31
121 if (rtt_phase_
== false) {
122 if (rtt_seenolderhigh_
) {
124 last_edge_time_
= last_sample_time_
;
125 send_rate_
+= randommod(send_rate_
/ 4);
128 if (rtt_seenolderlow_
) {
133 rtt_seenolderhigh_
= rtt_seenrecenthigh_
;
134 rtt_seenolderlow_
= rtt_seenrecentlow_
;
135 rtt_seenrecenthigh_
= false;
136 rtt_seenrecentlow_
= false;
138 AttemptToDoubleSendRate();
141 void RttAndSendRateCalculator::AttemptToDoubleSendRate() {
142 base::TimeDelta time_since_edge
= last_sample_time_
- last_edge_time_
;
143 base::TimeDelta time_since_doubling
=
144 last_sample_time_
- last_doubling_time_
;
148 if (time_since_edge
.InMicroseconds() <
149 base::Time::kMicrosecondsPerSecond
* 60) {
150 threshold
= (4 * send_rate_
) +
151 (64 * rtt_timeout_
) +
152 (5 * base::Time::kMicrosecondsPerSecond
);
154 threshold
= (4 * send_rate_
) +
157 if (time_since_doubling
.InMicroseconds() < threshold
)
164 last_doubling_time_
= last_sample_time_
;
167 // returns a random number from 0 to val-1.
168 int32
RttAndSendRateCalculator::randommod(int32 val
) {