Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(550)

Side by Side Diff: net/base/network_quality_estimator.cc

Issue 1164713004: Store network quality samples so we can compute percentiles. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Changes to make the tests work on Windows Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/base/network_quality_estimator.h ('k') | net/base/network_quality_estimator_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 <limits>
7 #include <string> 8 #include <string>
8 9
9 #include "base/logging.h" 10 #include "base/logging.h"
10 #include "base/metrics/histogram.h" 11 #include "base/metrics/histogram.h"
11 #include "net/base/net_util.h" 12 #include "net/base/net_util.h"
12 #include "net/base/network_quality.h" 13 #include "net/base/network_quality.h"
13 #include "net/url_request/url_request.h" 14 #include "net/url_request/url_request.h"
14 #include "url/gurl.h" 15 #include "url/gurl.h"
15 16
17 namespace {
18
19 // Maximum number of observations that can be held in the ObservationBuffer.
20 const size_t kMaximumObservationsBufferSize = 500;
21
22 } // namespace
23
16 namespace net { 24 namespace net {
17 25
18 NetworkQualityEstimator::NetworkQualityEstimator() 26 NetworkQualityEstimator::NetworkQualityEstimator()
19 : NetworkQualityEstimator(false) { 27 : NetworkQualityEstimator(false) {
20 } 28 }
21 29
22 NetworkQualityEstimator::NetworkQualityEstimator( 30 NetworkQualityEstimator::NetworkQualityEstimator(
23 bool allow_local_host_requests_for_tests) 31 bool allow_local_host_requests_for_tests)
24 : allow_localhost_requests_(allow_local_host_requests_for_tests), 32 : allow_localhost_requests_(allow_local_host_requests_for_tests),
25 last_connection_change_(base::TimeTicks::Now()), 33 last_connection_change_(base::TimeTicks::Now()),
26 current_connection_type_(NetworkChangeNotifier::GetConnectionType()), 34 current_connection_type_(NetworkChangeNotifier::GetConnectionType()),
27 bytes_read_since_last_connection_change_(false), 35 fastest_rtt_since_last_connection_change_(base::TimeDelta::Max()),
28 peak_kbps_since_last_connection_change_(0) { 36 peak_kbps_since_last_connection_change_(0) {
29 static_assert(kMinRequestDurationMicroseconds > 0, 37 static_assert(kMinRequestDurationMicroseconds > 0,
30 "Minimum request duration must be > 0"); 38 "Minimum request duration must be > 0");
31 NetworkChangeNotifier::AddConnectionTypeObserver(this); 39 NetworkChangeNotifier::AddConnectionTypeObserver(this);
32 } 40 }
33 41
34 NetworkQualityEstimator::~NetworkQualityEstimator() { 42 NetworkQualityEstimator::~NetworkQualityEstimator() {
35 DCHECK(thread_checker_.CalledOnValidThread()); 43 DCHECK(thread_checker_.CalledOnValidThread());
36 NetworkChangeNotifier::RemoveConnectionTypeObserver(this); 44 NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
37 } 45 }
38 46
39 void NetworkQualityEstimator::NotifyDataReceived(const URLRequest& request, 47 void NetworkQualityEstimator::NotifyDataReceived(
40 int64_t prefilter_bytes_read) { 48 const URLRequest& request,
49 int64_t cumulative_prefilter_bytes_read,
50 int64_t prefiltered_bytes_read) {
41 DCHECK(thread_checker_.CalledOnValidThread()); 51 DCHECK(thread_checker_.CalledOnValidThread());
42 DCHECK_GT(prefilter_bytes_read, 0); 52 DCHECK_GT(cumulative_prefilter_bytes_read, 0);
53 DCHECK_GT(prefiltered_bytes_read, 0);
43 54
44 if (!request.url().is_valid() || 55 if (!request.url().is_valid() ||
45 (!allow_localhost_requests_ && IsLocalhost(request.url().host())) || 56 (!allow_localhost_requests_ && IsLocalhost(request.url().host())) ||
46 !request.url().SchemeIsHTTPOrHTTPS() || 57 !request.url().SchemeIsHTTPOrHTTPS() ||
47 // Verify that response headers are received, so it can be ensured that 58 // Verify that response headers are received, so it can be ensured that
48 // response is not cached. 59 // response is not cached.
49 request.response_info().response_time.is_null() || request.was_cached() || 60 request.response_info().response_time.is_null() || request.was_cached() ||
50 request.creation_time() < last_connection_change_) { 61 request.creation_time() < last_connection_change_) {
51 return; 62 return;
52 } 63 }
53 64
54 base::TimeTicks now = base::TimeTicks::Now(); 65 base::TimeTicks now = base::TimeTicks::Now();
55 base::TimeDelta request_duration = now - request.creation_time(); 66 base::TimeDelta request_duration = now - request.creation_time();
56 DCHECK_GE(request_duration, base::TimeDelta()); 67 DCHECK_GE(request_duration, base::TimeDelta());
57 if (!bytes_read_since_last_connection_change_)
58 fastest_RTT_since_last_connection_change_ = request_duration;
59 68
60 bytes_read_since_last_connection_change_ = true; 69 // Only add RTT observation if this is the first read for this response.
61 if (request_duration < fastest_RTT_since_last_connection_change_) 70 if (cumulative_prefilter_bytes_read == prefiltered_bytes_read) {
62 fastest_RTT_since_last_connection_change_ = request_duration; 71 if (request_duration < fastest_rtt_since_last_connection_change_)
72 fastest_rtt_since_last_connection_change_ = request_duration;
73
74 rtt_msec_observations_.AddObservation(
75 Observation(request_duration.InMilliseconds(), now));
76 }
63 77
64 // Ignore tiny transfers which will not produce accurate rates. 78 // Ignore tiny transfers which will not produce accurate rates.
65 // Ignore short duration transfers. 79 // Ignore short duration transfers.
66 if (prefilter_bytes_read >= kMinTransferSizeInBytes && 80 if (cumulative_prefilter_bytes_read >= kMinTransferSizeInBytes &&
67 request_duration >= 81 request_duration >=
68 base::TimeDelta::FromMicroseconds(kMinRequestDurationMicroseconds)) { 82 base::TimeDelta::FromMicroseconds(kMinRequestDurationMicroseconds)) {
69 uint64_t kbps = static_cast<uint64_t>(prefilter_bytes_read * 8 * 1000 / 83 double kbps_f = cumulative_prefilter_bytes_read * 8.0 / 1000.0 /
70 request_duration.InMicroseconds()); 84 request_duration.InSecondsF();
71 if (kbps > peak_kbps_since_last_connection_change_) 85 DCHECK_GE(kbps_f, 0.0);
72 peak_kbps_since_last_connection_change_ = kbps; 86
87 // Check overflow errors. This may happen if the kbpsF is more than
88 // 2 * 10^9 (= 2000 Gbps).
89 if (kbps_f >= std::numeric_limits<int32_t>::max())
90 kbps_f = std::numeric_limits<int32_t>::max() - 1;
91
92 int32_t kbps = static_cast<int32_t>(kbps_f);
93
94 if (kbps > 0) {
95 if (kbps > peak_kbps_since_last_connection_change_)
96 peak_kbps_since_last_connection_change_ = kbps;
97
98 kbps_observations_.AddObservation(Observation(kbps, now));
99 }
73 } 100 }
74 } 101 }
75 102
76 void NetworkQualityEstimator::OnConnectionTypeChanged( 103 void NetworkQualityEstimator::OnConnectionTypeChanged(
77 NetworkChangeNotifier::ConnectionType type) { 104 NetworkChangeNotifier::ConnectionType type) {
78 DCHECK(thread_checker_.CalledOnValidThread()); 105 DCHECK(thread_checker_.CalledOnValidThread());
79 if (bytes_read_since_last_connection_change_) { 106 if (fastest_rtt_since_last_connection_change_ != base::TimeDelta::Max()) {
80 switch (current_connection_type_) { 107 switch (current_connection_type_) {
81 case NetworkChangeNotifier::CONNECTION_UNKNOWN: 108 case NetworkChangeNotifier::CONNECTION_UNKNOWN:
82 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.Unknown", 109 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.Unknown",
83 fastest_RTT_since_last_connection_change_); 110 fastest_rtt_since_last_connection_change_);
84 break; 111 break;
85 case NetworkChangeNotifier::CONNECTION_ETHERNET: 112 case NetworkChangeNotifier::CONNECTION_ETHERNET:
86 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.Ethernet", 113 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.Ethernet",
87 fastest_RTT_since_last_connection_change_); 114 fastest_rtt_since_last_connection_change_);
88 break; 115 break;
89 case NetworkChangeNotifier::CONNECTION_WIFI: 116 case NetworkChangeNotifier::CONNECTION_WIFI:
90 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.Wifi", 117 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.Wifi",
91 fastest_RTT_since_last_connection_change_); 118 fastest_rtt_since_last_connection_change_);
92 break; 119 break;
93 case NetworkChangeNotifier::CONNECTION_2G: 120 case NetworkChangeNotifier::CONNECTION_2G:
94 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.2G", 121 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.2G",
95 fastest_RTT_since_last_connection_change_); 122 fastest_rtt_since_last_connection_change_);
96 break; 123 break;
97 case NetworkChangeNotifier::CONNECTION_3G: 124 case NetworkChangeNotifier::CONNECTION_3G:
98 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.3G", 125 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.3G",
99 fastest_RTT_since_last_connection_change_); 126 fastest_rtt_since_last_connection_change_);
100 break; 127 break;
101 case NetworkChangeNotifier::CONNECTION_4G: 128 case NetworkChangeNotifier::CONNECTION_4G:
102 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.4G", 129 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.4G",
103 fastest_RTT_since_last_connection_change_); 130 fastest_rtt_since_last_connection_change_);
104 break; 131 break;
105 case NetworkChangeNotifier::CONNECTION_NONE: 132 case NetworkChangeNotifier::CONNECTION_NONE:
106 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.None", 133 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.None",
107 fastest_RTT_since_last_connection_change_); 134 fastest_rtt_since_last_connection_change_);
108 break; 135 break;
109 case NetworkChangeNotifier::CONNECTION_BLUETOOTH: 136 case NetworkChangeNotifier::CONNECTION_BLUETOOTH:
110 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.Bluetooth", 137 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.Bluetooth",
111 fastest_RTT_since_last_connection_change_); 138 fastest_rtt_since_last_connection_change_);
112 break; 139 break;
113 default: 140 default:
114 NOTREACHED(); 141 NOTREACHED();
115 break; 142 break;
116 } 143 }
117 } 144 }
118 145
119 if (peak_kbps_since_last_connection_change_) { 146 if (peak_kbps_since_last_connection_change_) {
120 switch (current_connection_type_) { 147 switch (current_connection_type_) {
121 case NetworkChangeNotifier::CONNECTION_UNKNOWN: 148 case NetworkChangeNotifier::CONNECTION_UNKNOWN:
(...skipping 28 matching lines...) Expand all
150 UMA_HISTOGRAM_COUNTS("NQE.PeakKbps.Bluetooth", 177 UMA_HISTOGRAM_COUNTS("NQE.PeakKbps.Bluetooth",
151 peak_kbps_since_last_connection_change_); 178 peak_kbps_since_last_connection_change_);
152 break; 179 break;
153 default: 180 default:
154 NOTREACHED(); 181 NOTREACHED();
155 break; 182 break;
156 } 183 }
157 } 184 }
158 185
159 last_connection_change_ = base::TimeTicks::Now(); 186 last_connection_change_ = base::TimeTicks::Now();
160 bytes_read_since_last_connection_change_ = false;
161 peak_kbps_since_last_connection_change_ = 0; 187 peak_kbps_since_last_connection_change_ = 0;
188 fastest_rtt_since_last_connection_change_ = base::TimeDelta::Max();
189 kbps_observations_.Clear();
190 rtt_msec_observations_.Clear();
162 current_connection_type_ = type; 191 current_connection_type_ = type;
163 } 192 }
164 193
165 NetworkQuality NetworkQualityEstimator::GetEstimate() const { 194 NetworkQuality NetworkQualityEstimator::GetPeakEstimate() const {
166 DCHECK(thread_checker_.CalledOnValidThread()); 195 DCHECK(thread_checker_.CalledOnValidThread());
167 196
168 if (!bytes_read_since_last_connection_change_) { 197 return NetworkQuality(fastest_rtt_since_last_connection_change_,
169 return NetworkQuality(fastest_RTT_since_last_connection_change_, 0, 198 peak_kbps_since_last_connection_change_);
170 peak_kbps_since_last_connection_change_, 0); 199 }
171 } 200
172 if (!peak_kbps_since_last_connection_change_) { 201 size_t NetworkQualityEstimator::GetMaximumObservationBufferSizeForTests()
173 return NetworkQuality(fastest_RTT_since_last_connection_change_, 0.1, 202 const {
174 peak_kbps_since_last_connection_change_, 0); 203 return kMaximumObservationsBufferSize;
175 } 204 }
176 return NetworkQuality(fastest_RTT_since_last_connection_change_, 0.1, 205
177 peak_kbps_since_last_connection_change_, 0.1); 206 bool NetworkQualityEstimator::VerifyBufferSizeForTests(
207 size_t expected_size) const {
208 return kbps_observations_.Size() == expected_size &&
209 rtt_msec_observations_.Size() == expected_size;
210 }
211
212 NetworkQualityEstimator::Observation::Observation(int32_t value,
213 base::TimeTicks timestamp)
214 : value(value), timestamp(timestamp) {
215 DCHECK_GE(value, 0);
216 DCHECK(!timestamp.is_null());
217 }
218
219 NetworkQualityEstimator::Observation::~Observation() {
220 }
221
222 NetworkQualityEstimator::ObservationBuffer::ObservationBuffer() {
223 static_assert(kMaximumObservationsBufferSize > 0U,
224 "Minimum size of observation buffer must be > 0");
225 }
226
227 NetworkQualityEstimator::ObservationBuffer::~ObservationBuffer() {
228 }
229
230 void NetworkQualityEstimator::ObservationBuffer::AddObservation(
231 const Observation& observation) {
232 DCHECK_LE(observations_.size(), kMaximumObservationsBufferSize);
233 // Evict the oldest element if the buffer is already full.
234 if (observations_.size() == kMaximumObservationsBufferSize)
235 observations_.pop_front();
236
237 observations_.push_back(observation);
238 DCHECK_LE(observations_.size(), kMaximumObservationsBufferSize);
239 }
240
241 size_t NetworkQualityEstimator::ObservationBuffer::Size() const {
242 return observations_.size();
243 }
244
245 void NetworkQualityEstimator::ObservationBuffer::Clear() {
246 observations_.clear();
247 DCHECK(observations_.empty());
178 } 248 }
179 249
180 } // namespace net 250 } // namespace net
OLDNEW
« no previous file with comments | « net/base/network_quality_estimator.h ('k') | net/base/network_quality_estimator_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698