OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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/base/network_quality_estimator.h" | 5 #include "net/base/network_quality_estimator.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/logging.h" | |
9 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
10 #include "net/base/net_util.h" | 11 #include "net/base/net_util.h" |
11 #include "net/base/network_quality.h" | 12 #include "net/base/network_quality.h" |
12 #include "net/url_request/url_request.h" | 13 #include "net/url_request/url_request.h" |
13 #include "url/gurl.h" | 14 #include "url/gurl.h" |
14 | 15 |
16 namespace { | |
17 | |
18 // Maximum number of samples to hold in the buffer for network quality | |
19 // estimation. | |
20 const uint32_t kMaximumSamples = 300; | |
21 | |
22 } // namespace | |
23 | |
15 namespace net { | 24 namespace net { |
16 | 25 |
17 NetworkQualityEstimator::NetworkQualityEstimator() | 26 NetworkQualityEstimator::NetworkQualityEstimator() |
18 : NetworkQualityEstimator(false) { | 27 : NetworkQualityEstimator(false) { |
19 } | 28 } |
20 | 29 |
21 NetworkQualityEstimator::NetworkQualityEstimator( | 30 NetworkQualityEstimator::NetworkQualityEstimator( |
22 bool allow_local_host_requests_for_tests) | 31 bool allow_local_host_requests_for_tests) |
23 : allow_localhost_requests_(allow_local_host_requests_for_tests), | 32 : allow_localhost_requests_(allow_local_host_requests_for_tests), |
24 last_connection_change_(base::TimeTicks::Now()), | 33 last_connection_change_(base::TimeTicks::Now()), |
25 current_connection_type_(NetworkChangeNotifier::GetConnectionType()), | 34 current_connection_type_(NetworkChangeNotifier::GetConnectionType()), |
26 bytes_read_since_last_connection_change_(false), | 35 bytes_read_since_last_connection_change_(false), |
27 peak_kbps_since_last_connection_change_(0) { | 36 peak_kbps_since_last_connection_change_(0) { |
28 static_assert(kMinRequestDurationMicroseconds > 0, | 37 static_assert(kMinRequestDurationMicroseconds > 0, |
29 "Minimum request duration must be > 0"); | 38 "Minimum request duration must be > 0"); |
39 static_assert(kMaximumSamples > 0, | |
40 "Buffer size for storing network quality samples must be > 0"); | |
30 NetworkChangeNotifier::AddConnectionTypeObserver(this); | 41 NetworkChangeNotifier::AddConnectionTypeObserver(this); |
31 } | 42 } |
32 | 43 |
33 NetworkQualityEstimator::~NetworkQualityEstimator() { | 44 NetworkQualityEstimator::~NetworkQualityEstimator() { |
34 DCHECK(thread_checker_.CalledOnValidThread()); | 45 DCHECK(thread_checker_.CalledOnValidThread()); |
35 NetworkChangeNotifier::RemoveConnectionTypeObserver(this); | 46 NetworkChangeNotifier::RemoveConnectionTypeObserver(this); |
36 } | 47 } |
37 | 48 |
38 void NetworkQualityEstimator::NotifyDataReceived(const URLRequest& request, | 49 void NetworkQualityEstimator::NotifyDataReceived( |
39 int64_t prefilter_bytes_read) { | 50 const URLRequest& request, |
51 int64_t cummulative_prefilter_bytes_read, | |
52 int64_t prefiltered_bytes_read) { | |
40 DCHECK(thread_checker_.CalledOnValidThread()); | 53 DCHECK(thread_checker_.CalledOnValidThread()); |
41 DCHECK_GT(prefilter_bytes_read, 0); | 54 DCHECK_GT(cummulative_prefilter_bytes_read, 0); |
55 DCHECK_GT(prefiltered_bytes_read, 0); | |
42 | 56 |
43 if (!request.url().is_valid() || | 57 if (!request.url().is_valid() || |
44 (!allow_localhost_requests_ && IsLocalhost(request.url().host())) || | 58 (!allow_localhost_requests_ && IsLocalhost(request.url().host())) || |
45 !request.url().SchemeIsHTTPOrHTTPS() || | 59 !request.url().SchemeIsHTTPOrHTTPS() || |
46 // Verify that response headers are received, so it can be ensured that | 60 // Verify that response headers are received, so it can be ensured that |
47 // response is not cached. | 61 // response is not cached. |
48 request.response_info().response_time.is_null() || request.was_cached()) | 62 request.response_info().response_time.is_null() || request.was_cached() || |
63 request.creation_time() < last_connection_change_) { | |
49 return; | 64 return; |
65 } | |
50 | 66 |
51 base::TimeTicks now = base::TimeTicks::Now(); | 67 base::TimeTicks now = base::TimeTicks::Now(); |
52 base::TimeDelta request_duration = now - request.creation_time(); | 68 base::TimeDelta request_duration = now - request.creation_time(); |
53 DCHECK_GE(request_duration, base::TimeDelta()); | 69 DCHECK_GE(request_duration, base::TimeDelta()); |
54 if (!bytes_read_since_last_connection_change_) | 70 if (!bytes_read_since_last_connection_change_) |
55 fastest_RTT_since_last_connection_change_ = request_duration; | 71 fastest_RTT_since_last_connection_change_ = request_duration; |
56 | 72 |
57 bytes_read_since_last_connection_change_ = true; | 73 bytes_read_since_last_connection_change_ = true; |
58 if (request_duration < fastest_RTT_since_last_connection_change_) | 74 if (request_duration < fastest_RTT_since_last_connection_change_) |
59 fastest_RTT_since_last_connection_change_ = request_duration; | 75 fastest_RTT_since_last_connection_change_ = request_duration; |
60 | 76 |
77 // Only add RTT sample if this is the first read for this response. | |
78 if (cummulative_prefilter_bytes_read == prefiltered_bytes_read) { | |
79 // Pop the oldest element if the buffer is already full. | |
80 if (rtt_msec_.size() >= kMaximumSamples) | |
bengr
2015/06/01 22:55:42
Perhaps use a while loop, for better future proofi
tbansal1
2015/06/02 18:33:01
Added
DCHECK_LE(samples_.size(), kMaximumSamples);
| |
81 rtt_msec_.pop_front(); | |
82 | |
83 rtt_msec_.push_back(Sample(request_duration.InMilliseconds())); | |
84 } | |
85 DCHECK_LE(rtt_msec_.size(), kMaximumSamples); | |
86 | |
61 // Ignore tiny transfers which will not produce accurate rates. | 87 // Ignore tiny transfers which will not produce accurate rates. |
62 // Ignore short duration transfers. | 88 // Ignore short duration transfers. |
63 if (prefilter_bytes_read >= kMinTransferSizeInBytes && | 89 if (cummulative_prefilter_bytes_read >= kMinTransferSizeInBytes && |
64 request_duration >= | 90 request_duration >= |
65 base::TimeDelta::FromMicroseconds(kMinRequestDurationMicroseconds) && | 91 base::TimeDelta::FromMicroseconds(kMinRequestDurationMicroseconds)) { |
66 request.creation_time() > last_connection_change_) { | 92 uint64_t kbps = |
67 uint64_t kbps = static_cast<uint64_t>(prefilter_bytes_read * 8 * 1000 / | 93 static_cast<uint64_t>(cummulative_prefilter_bytes_read * 8 * 1000 / |
68 request_duration.InMicroseconds()); | 94 request_duration.InMicroseconds()); |
69 if (kbps > peak_kbps_since_last_connection_change_) | 95 if (kbps > peak_kbps_since_last_connection_change_) |
70 peak_kbps_since_last_connection_change_ = kbps; | 96 peak_kbps_since_last_connection_change_ = kbps; |
97 | |
98 // Pop the oldest element if the buffer is already full. | |
bengr
2015/06/01 22:55:42
You should probably write a ring buffer instead of
tbansal1
2015/06/02 18:33:01
Done.
| |
99 if (kbps_.size() >= kMaximumSamples) | |
bengr
2015/06/01 22:55:42
Perhaps use a while loop, for better future proofi
tbansal1
2015/06/02 18:33:01
Please see the comment above.
| |
100 kbps_.pop_front(); | |
101 | |
102 kbps_.push_back(Sample(kbps)); | |
103 DCHECK_LE(kbps_.size(), kMaximumSamples); | |
71 } | 104 } |
72 } | 105 } |
73 | 106 |
74 void NetworkQualityEstimator::OnConnectionTypeChanged( | 107 void NetworkQualityEstimator::OnConnectionTypeChanged( |
75 NetworkChangeNotifier::ConnectionType type) { | 108 NetworkChangeNotifier::ConnectionType type) { |
76 DCHECK(thread_checker_.CalledOnValidThread()); | 109 DCHECK(thread_checker_.CalledOnValidThread()); |
77 if (bytes_read_since_last_connection_change_) { | 110 if (bytes_read_since_last_connection_change_) { |
78 switch (current_connection_type_) { | 111 switch (current_connection_type_) { |
79 case NetworkChangeNotifier::CONNECTION_UNKNOWN: | 112 case NetworkChangeNotifier::CONNECTION_UNKNOWN: |
80 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.Unknown", | 113 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.Unknown", |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
153 break; | 186 break; |
154 } | 187 } |
155 } | 188 } |
156 | 189 |
157 last_connection_change_ = base::TimeTicks::Now(); | 190 last_connection_change_ = base::TimeTicks::Now(); |
158 bytes_read_since_last_connection_change_ = false; | 191 bytes_read_since_last_connection_change_ = false; |
159 peak_kbps_since_last_connection_change_ = 0; | 192 peak_kbps_since_last_connection_change_ = 0; |
160 current_connection_type_ = type; | 193 current_connection_type_ = type; |
161 } | 194 } |
162 | 195 |
163 NetworkQuality NetworkQualityEstimator::GetEstimate() const { | 196 NetworkQuality NetworkQualityEstimator::GetPeakEstimate() const { |
164 DCHECK(thread_checker_.CalledOnValidThread()); | 197 DCHECK(thread_checker_.CalledOnValidThread()); |
165 | 198 |
166 if (!bytes_read_since_last_connection_change_) { | 199 if (!bytes_read_since_last_connection_change_) { |
167 return NetworkQuality(fastest_RTT_since_last_connection_change_, 0, | 200 return NetworkQuality(fastest_RTT_since_last_connection_change_, 0, |
168 peak_kbps_since_last_connection_change_, 0); | 201 peak_kbps_since_last_connection_change_, 0); |
169 } | 202 } |
170 if (!peak_kbps_since_last_connection_change_) { | 203 if (!peak_kbps_since_last_connection_change_) { |
171 return NetworkQuality(fastest_RTT_since_last_connection_change_, 0.1, | 204 return NetworkQuality(fastest_RTT_since_last_connection_change_, 0.1, |
172 peak_kbps_since_last_connection_change_, 0); | 205 peak_kbps_since_last_connection_change_, 0); |
173 } | 206 } |
174 return NetworkQuality(fastest_RTT_since_last_connection_change_, 0.1, | 207 return NetworkQuality(fastest_RTT_since_last_connection_change_, 0.1, |
175 peak_kbps_since_last_connection_change_, 0.1); | 208 peak_kbps_since_last_connection_change_, 0.1); |
176 } | 209 } |
177 | 210 |
211 NetworkQualityEstimator::Sample::Sample(int value) | |
212 : value_(value), timestamp_(base::TimeTicks::Now()) { | |
213 DCHECK_GE(value_, 0); | |
214 } | |
215 | |
178 } // namespace net | 216 } // namespace net |
OLD | NEW |