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

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: Addressed bengr comments 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
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 <string> 7 #include <string>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/metrics/histogram.h" 10 #include "base/metrics/histogram.h"
11 #include "net/base/net_util.h" 11 #include "net/base/net_util.h"
12 #include "net/base/network_quality.h" 12 #include "net/base/network_quality.h"
13 #include "net/url_request/url_request.h" 13 #include "net/url_request/url_request.h"
14 #include "url/gurl.h" 14 #include "url/gurl.h"
15 15
16 namespace net { 16 namespace net {
17 17
18 // Maximum number of observations to hold in the ObservationBuffer.
19 const size_t NetworkQualityEstimator::ObservationBuffer::kMaximumObservations =
20 500;
21
18 NetworkQualityEstimator::NetworkQualityEstimator() 22 NetworkQualityEstimator::NetworkQualityEstimator()
19 : NetworkQualityEstimator(false) { 23 : NetworkQualityEstimator(false) {
20 } 24 }
21 25
22 NetworkQualityEstimator::NetworkQualityEstimator( 26 NetworkQualityEstimator::NetworkQualityEstimator(
23 bool allow_local_host_requests_for_tests) 27 bool allow_local_host_requests_for_tests)
24 : allow_localhost_requests_(allow_local_host_requests_for_tests), 28 : allow_localhost_requests_(allow_local_host_requests_for_tests),
25 last_connection_change_(base::TimeTicks::Now()), 29 last_connection_change_(base::TimeTicks::Now()),
26 current_connection_type_(NetworkChangeNotifier::GetConnectionType()), 30 current_connection_type_(NetworkChangeNotifier::GetConnectionType()),
27 bytes_read_since_last_connection_change_(false), 31 have_received_bytes_since_last_connection_change_(false),
28 peak_kbps_since_last_connection_change_(0) { 32 peak_kbps_since_last_connection_change_(0) {
29 static_assert(kMinRequestDurationMicroseconds > 0, 33 static_assert(kMinRequestDurationMicroseconds > 0,
30 "Minimum request duration must be > 0"); 34 "Minimum request duration must be > 0");
31 NetworkChangeNotifier::AddConnectionTypeObserver(this); 35 NetworkChangeNotifier::AddConnectionTypeObserver(this);
32 } 36 }
33 37
34 NetworkQualityEstimator::~NetworkQualityEstimator() { 38 NetworkQualityEstimator::~NetworkQualityEstimator() {
35 DCHECK(thread_checker_.CalledOnValidThread()); 39 DCHECK(thread_checker_.CalledOnValidThread());
36 NetworkChangeNotifier::RemoveConnectionTypeObserver(this); 40 NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
37 } 41 }
38 42
39 void NetworkQualityEstimator::NotifyDataReceived(const URLRequest& request, 43 void NetworkQualityEstimator::NotifyDataReceived(
40 int64_t prefilter_bytes_read) { 44 const URLRequest& request,
45 int64_t cumulative_prefilter_bytes_read,
46 int64_t prefiltered_bytes_read) {
41 DCHECK(thread_checker_.CalledOnValidThread()); 47 DCHECK(thread_checker_.CalledOnValidThread());
42 DCHECK_GT(prefilter_bytes_read, 0); 48 DCHECK_GT(cumulative_prefilter_bytes_read, 0);
49 DCHECK_GT(prefiltered_bytes_read, 0);
43 50
44 if (!request.url().is_valid() || 51 if (!request.url().is_valid() ||
45 (!allow_localhost_requests_ && IsLocalhost(request.url().host())) || 52 (!allow_localhost_requests_ && IsLocalhost(request.url().host())) ||
46 !request.url().SchemeIsHTTPOrHTTPS() || 53 !request.url().SchemeIsHTTPOrHTTPS() ||
47 // Verify that response headers are received, so it can be ensured that 54 // Verify that response headers are received, so it can be ensured that
48 // response is not cached. 55 // response is not cached.
49 request.response_info().response_time.is_null() || request.was_cached() || 56 request.response_info().response_time.is_null() || request.was_cached() ||
50 request.creation_time() < last_connection_change_) { 57 request.creation_time() < last_connection_change_) {
51 return; 58 return;
52 } 59 }
53 60
54 base::TimeTicks now = base::TimeTicks::Now(); 61 base::TimeTicks now = base::TimeTicks::Now();
55 base::TimeDelta request_duration = now - request.creation_time(); 62 base::TimeDelta request_duration = now - request.creation_time();
56 DCHECK_GE(request_duration, base::TimeDelta()); 63 DCHECK_GE(request_duration, base::TimeDelta());
mmenke 2015/06/11 15:11:01 If this is 0, we're in trouble, aren't we? Should
tbansal1 2015/06/11 19:27:50 We may not be in trouble. It will cause peak_rtt t
57 if (!bytes_read_since_last_connection_change_) 64 if (!have_received_bytes_since_last_connection_change_)
58 fastest_RTT_since_last_connection_change_ = request_duration; 65 fastest_rtt_since_last_connection_change_ = request_duration;
59 66
60 bytes_read_since_last_connection_change_ = true; 67 have_received_bytes_since_last_connection_change_ = true;
61 if (request_duration < fastest_RTT_since_last_connection_change_) 68 if (request_duration < fastest_rtt_since_last_connection_change_)
62 fastest_RTT_since_last_connection_change_ = request_duration; 69 fastest_rtt_since_last_connection_change_ = request_duration;
mmenke 2015/06/11 15:11:01 Suggest only doing this if cumulative_prefilter_by
tbansal1 2015/06/11 19:27:50 Can you please explain why this should be done onl
mmenke 2015/06/11 19:51:18 RTT should be from when we send the headers to whe
tbansal1 2015/06/11 21:16:29 Right, it makes sense to do RTT only when cumulati
70
71 // Only add RTT observation if this is the first read for this response.
72 if (cumulative_prefilter_bytes_read == prefiltered_bytes_read)
73 rtt_msec_observations_.AddObservation(request_duration.InMilliseconds());
63 74
64 // Ignore tiny transfers which will not produce accurate rates. 75 // Ignore tiny transfers which will not produce accurate rates.
65 // Ignore short duration transfers. 76 // Ignore short duration transfers.
66 if (prefilter_bytes_read >= kMinTransferSizeInBytes && 77 if (cumulative_prefilter_bytes_read >= kMinTransferSizeInBytes &&
67 request_duration >= 78 request_duration >=
68 base::TimeDelta::FromMicroseconds(kMinRequestDurationMicroseconds)) { 79 base::TimeDelta::FromMicroseconds(kMinRequestDurationMicroseconds)) {
69 uint64_t kbps = static_cast<uint64_t>(prefilter_bytes_read * 8 * 1000 / 80 int32_t kbps =
70 request_duration.InMicroseconds()); 81 static_cast<int32_t>(cumulative_prefilter_bytes_read * 8 * 1000 /
82 request_duration.InMicroseconds());
mmenke 2015/06/11 15:11:01 Should handle overflow here. Unlikely, even for l
tbansal1 2015/06/11 19:27:50 I was handling the overflow in AddObservation() bu
71 if (kbps > peak_kbps_since_last_connection_change_) 83 if (kbps > peak_kbps_since_last_connection_change_)
72 peak_kbps_since_last_connection_change_ = kbps; 84 peak_kbps_since_last_connection_change_ = kbps;
85
86 kbps_observations_.AddObservation(kbps);
73 } 87 }
74 } 88 }
75 89
76 void NetworkQualityEstimator::OnConnectionTypeChanged( 90 void NetworkQualityEstimator::OnConnectionTypeChanged(
77 NetworkChangeNotifier::ConnectionType type) { 91 NetworkChangeNotifier::ConnectionType type) {
78 DCHECK(thread_checker_.CalledOnValidThread()); 92 DCHECK(thread_checker_.CalledOnValidThread());
79 if (bytes_read_since_last_connection_change_) { 93 if (have_received_bytes_since_last_connection_change_) {
80 switch (current_connection_type_) { 94 switch (current_connection_type_) {
81 case NetworkChangeNotifier::CONNECTION_UNKNOWN: 95 case NetworkChangeNotifier::CONNECTION_UNKNOWN:
82 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.Unknown", 96 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.Unknown",
83 fastest_RTT_since_last_connection_change_); 97 fastest_rtt_since_last_connection_change_);
84 break; 98 break;
85 case NetworkChangeNotifier::CONNECTION_ETHERNET: 99 case NetworkChangeNotifier::CONNECTION_ETHERNET:
86 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.Ethernet", 100 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.Ethernet",
87 fastest_RTT_since_last_connection_change_); 101 fastest_rtt_since_last_connection_change_);
88 break; 102 break;
89 case NetworkChangeNotifier::CONNECTION_WIFI: 103 case NetworkChangeNotifier::CONNECTION_WIFI:
90 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.Wifi", 104 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.Wifi",
91 fastest_RTT_since_last_connection_change_); 105 fastest_rtt_since_last_connection_change_);
92 break; 106 break;
93 case NetworkChangeNotifier::CONNECTION_2G: 107 case NetworkChangeNotifier::CONNECTION_2G:
94 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.2G", 108 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.2G",
95 fastest_RTT_since_last_connection_change_); 109 fastest_rtt_since_last_connection_change_);
96 break; 110 break;
97 case NetworkChangeNotifier::CONNECTION_3G: 111 case NetworkChangeNotifier::CONNECTION_3G:
98 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.3G", 112 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.3G",
99 fastest_RTT_since_last_connection_change_); 113 fastest_rtt_since_last_connection_change_);
100 break; 114 break;
101 case NetworkChangeNotifier::CONNECTION_4G: 115 case NetworkChangeNotifier::CONNECTION_4G:
102 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.4G", 116 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.4G",
103 fastest_RTT_since_last_connection_change_); 117 fastest_rtt_since_last_connection_change_);
104 break; 118 break;
105 case NetworkChangeNotifier::CONNECTION_NONE: 119 case NetworkChangeNotifier::CONNECTION_NONE:
106 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.None", 120 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.None",
107 fastest_RTT_since_last_connection_change_); 121 fastest_rtt_since_last_connection_change_);
108 break; 122 break;
109 case NetworkChangeNotifier::CONNECTION_BLUETOOTH: 123 case NetworkChangeNotifier::CONNECTION_BLUETOOTH:
110 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.Bluetooth", 124 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.Bluetooth",
111 fastest_RTT_since_last_connection_change_); 125 fastest_rtt_since_last_connection_change_);
112 break; 126 break;
113 default: 127 default:
114 NOTREACHED(); 128 NOTREACHED();
115 break; 129 break;
116 } 130 }
117 } 131 }
118 132
119 if (peak_kbps_since_last_connection_change_) { 133 if (peak_kbps_since_last_connection_change_) {
120 switch (current_connection_type_) { 134 switch (current_connection_type_) {
121 case NetworkChangeNotifier::CONNECTION_UNKNOWN: 135 case NetworkChangeNotifier::CONNECTION_UNKNOWN:
(...skipping 28 matching lines...) Expand all
150 UMA_HISTOGRAM_COUNTS("NQE.PeakKbps.Bluetooth", 164 UMA_HISTOGRAM_COUNTS("NQE.PeakKbps.Bluetooth",
151 peak_kbps_since_last_connection_change_); 165 peak_kbps_since_last_connection_change_);
152 break; 166 break;
153 default: 167 default:
154 NOTREACHED(); 168 NOTREACHED();
155 break; 169 break;
156 } 170 }
157 } 171 }
158 172
159 last_connection_change_ = base::TimeTicks::Now(); 173 last_connection_change_ = base::TimeTicks::Now();
160 bytes_read_since_last_connection_change_ = false; 174 have_received_bytes_since_last_connection_change_ = false;
161 peak_kbps_since_last_connection_change_ = 0; 175 peak_kbps_since_last_connection_change_ = 0;
162 current_connection_type_ = type; 176 current_connection_type_ = type;
mmenke 2015/06/11 15:11:01 Should we throw out our observations here? If so,
tbansal1 2015/06/11 19:27:50 Yes, we should. This was part of the bigger CL (th
163 } 177 }
164 178
165 NetworkQuality NetworkQualityEstimator::GetEstimate() const { 179 NetworkQuality NetworkQualityEstimator::GetPeakEstimate() const {
166 DCHECK(thread_checker_.CalledOnValidThread()); 180 DCHECK(thread_checker_.CalledOnValidThread());
167 181
168 if (!bytes_read_since_last_connection_change_) { 182 if (!have_received_bytes_since_last_connection_change_)
169 return NetworkQuality(fastest_RTT_since_last_connection_change_, 0, 183 return NetworkQuality(base::TimeDelta(), 0);
mmenke 2015/06/11 15:11:01 Returning 0 as the default peak transfer rate seem
tbansal1 2015/06/11 19:27:50 Done. Default rtt is now base::TimeDelta::Max(). T
170 peak_kbps_since_last_connection_change_, 0); 184 if (!peak_kbps_since_last_connection_change_)
171 } 185 return NetworkQuality(fastest_rtt_since_last_connection_change_, 0);
172 if (!peak_kbps_since_last_connection_change_) { 186 return NetworkQuality(fastest_rtt_since_last_connection_change_,
173 return NetworkQuality(fastest_RTT_since_last_connection_change_, 0.1, 187 peak_kbps_since_last_connection_change_);
174 peak_kbps_since_last_connection_change_, 0); 188 }
175 } 189
176 return NetworkQuality(fastest_RTT_since_last_connection_change_, 0.1, 190 NetworkQualityEstimator::Observation::Observation(int32_t value,
177 peak_kbps_since_last_connection_change_, 0.1); 191 base::TimeTicks timestamp)
192 : value(value), timestamp(timestamp) {
193 DCHECK_GE(value, 0);
194 }
195
196 NetworkQualityEstimator::Observation::~Observation() {
197 }
198
199 NetworkQualityEstimator::ObservationBuffer::ObservationBuffer() {
200 static_assert(kMaximumObservations > 0U,
201 "Minimum size of observation buffer must be > 0");
mmenke 2015/06/11 15:11:01 This should go just under the line where you defin
tbansal1 2015/06/11 19:27:50 Problem there is that it does not compile because
202 }
203
204 NetworkQualityEstimator::ObservationBuffer::~ObservationBuffer() {
205 }
206
207 void NetworkQualityEstimator::ObservationBuffer::AddObservation(int32_t value) {
208 DCHECK_LE(observations_.size(), kMaximumObservations);
209 if (value < 0)
mmenke 2015/06/11 15:11:01 When can this happen?
tbansal1 2015/06/11 19:27:50 This is for the case if there is an overflow on th
210 return;
211 // Pop the oldest element if the buffer is already full.
212 if (observations_.size() == kMaximumObservations)
213 observations_.pop_front();
214
215 observations_.push_back(Observation(value, base::TimeTicks::Now()));
mmenke 2015/06/11 15:11:01 Suggest passing base::TimeTicks::Now() in as an ar
tbansal1 2015/06/11 19:27:50 Done.
216 DCHECK_LE(observations_.size(), kMaximumObservations);
217 }
218
219 size_t NetworkQualityEstimator::ObservationBuffer::size() const {
mmenke 2015/06/11 15:11:01 If this isn't inlined in the header, it should be
tbansal1 2015/06/11 19:27:50 Done.
220 return observations_.size();
178 } 221 }
179 222
180 } // namespace net 223 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698