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

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

Issue 1144163008: Add in-memory caching of network quality estimates across network changes. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Minor modifications to comments and code 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/metrics/histogram.h" 9 #include "base/metrics/histogram.h"
10 #include "net/base/net_util.h" 10 #include "net/base/net_util.h"
11 #include "net/base/network_quality.h" 11 #include "net/base/network_quality.h"
12 #include "net/url_request/url_request.h" 12 #include "net/url_request/url_request.h"
13 #include "url/gurl.h" 13 #include "url/gurl.h"
14 14
15 #if defined(OS_ANDROID)
16 #include "net/android/network_library.h"
17 #endif // OS_ANDROID
18
19 namespace {
20
21 // Maximum size of the cache that holds network quality estimates.
22 // Smaller size may reduce the cache hit rate due to frequent evictions.
23 // Larger size may affect performance.
24 const uint32_t kMaximumNetworkQualityCacheSize = 5;
25
26 } // namespace
27
15 namespace net { 28 namespace net {
16 29
30 CachedNetworkQuality::CachedNetworkQuality(
31 NetworkChangeNotifier::ConnectionType connection_type,
32 std::string network_name,
33 int median_kbps,
34 int median_rtt_milliseconds)
35 : connection_type(connection_type),
36 network_name(network_name),
37 median_kbps(median_kbps),
38 median_rtt_milliseconds(median_rtt_milliseconds),
39 last_updated(base::TimeTicks::Now()) {
40 DCHECK_NE(network_name, std::string());
41 }
42
43 CachedNetworkQuality::~CachedNetworkQuality() {
44 }
45
46 void CachedNetworkQuality::UpdateNetworkQuality(
47 int updated_median_kbps,
48 int updated_median_rtt_milliseconds) {
49 median_kbps = updated_median_kbps;
50 median_rtt_milliseconds = updated_median_rtt_milliseconds;
51 last_updated = base::TimeTicks::Now();
52 }
53
17 NetworkQualityEstimator::NetworkQualityEstimator() 54 NetworkQualityEstimator::NetworkQualityEstimator()
18 : NetworkQualityEstimator(false) { 55 : NetworkQualityEstimator(false) {
19 } 56 }
20 57
21 NetworkQualityEstimator::NetworkQualityEstimator( 58 NetworkQualityEstimator::NetworkQualityEstimator(
22 bool allow_local_host_requests_for_tests) 59 bool allow_local_host_requests_for_tests)
23 : allow_localhost_requests_(allow_local_host_requests_for_tests), 60 : allow_localhost_requests_(allow_local_host_requests_for_tests),
24 last_connection_change_(base::TimeTicks::Now()), 61 last_connection_change_(base::TimeTicks::Now()),
25 current_connection_type_(NetworkChangeNotifier::GetConnectionType()), 62 current_connection_type_(NetworkChangeNotifier::GetConnectionType()),
26 bytes_read_since_last_connection_change_(false), 63 bytes_read_since_last_connection_change_(false),
27 peak_kbps_since_last_connection_change_(0) { 64 peak_kbps_since_last_connection_change_(0) {
28 static_assert(kMinRequestDurationMicroseconds > 0, 65 static_assert(kMinRequestDurationMicroseconds > 0,
29 "Minimum request duration must be > 0"); 66 "Minimum request duration must be > 0");
67 static_assert(kMaximumNetworkQualityCacheSize > 0,
68 "Size of the network quality cache must be > 0");
30 NetworkChangeNotifier::AddConnectionTypeObserver(this); 69 NetworkChangeNotifier::AddConnectionTypeObserver(this);
70 current_network_name_ = GetCurrentNetworkName();
31 } 71 }
32 72
33 NetworkQualityEstimator::~NetworkQualityEstimator() { 73 NetworkQualityEstimator::~NetworkQualityEstimator() {
34 DCHECK(thread_checker_.CalledOnValidThread()); 74 DCHECK(thread_checker_.CalledOnValidThread());
35 NetworkChangeNotifier::RemoveConnectionTypeObserver(this); 75 NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
36 } 76 }
37 77
38 void NetworkQualityEstimator::NotifyDataReceived(const URLRequest& request, 78 void NetworkQualityEstimator::NotifyDataReceived(const URLRequest& request,
39 int64_t prefilter_bytes_read) { 79 int64_t prefilter_bytes_read) {
40 DCHECK(thread_checker_.CalledOnValidThread()); 80 DCHECK(thread_checker_.CalledOnValidThread());
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
102 break; 142 break;
103 case NetworkChangeNotifier::CONNECTION_NONE: 143 case NetworkChangeNotifier::CONNECTION_NONE:
104 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.None", 144 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.None",
105 fastest_RTT_since_last_connection_change_); 145 fastest_RTT_since_last_connection_change_);
106 break; 146 break;
107 case NetworkChangeNotifier::CONNECTION_BLUETOOTH: 147 case NetworkChangeNotifier::CONNECTION_BLUETOOTH:
108 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.Bluetooth", 148 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.Bluetooth",
109 fastest_RTT_since_last_connection_change_); 149 fastest_RTT_since_last_connection_change_);
110 break; 150 break;
111 default: 151 default:
112 NOTREACHED(); 152 NOTREACHED() << "Unexpected connection type = "
153 << current_connection_type_;
113 break; 154 break;
114 } 155 }
115 } 156 }
116 157
117 if (peak_kbps_since_last_connection_change_) { 158 if (peak_kbps_since_last_connection_change_) {
118 switch (current_connection_type_) { 159 switch (current_connection_type_) {
119 case NetworkChangeNotifier::CONNECTION_UNKNOWN: 160 case NetworkChangeNotifier::CONNECTION_UNKNOWN:
120 UMA_HISTOGRAM_COUNTS("NQE.PeakKbps.Unknown", 161 UMA_HISTOGRAM_COUNTS("NQE.PeakKbps.Unknown",
121 peak_kbps_since_last_connection_change_); 162 peak_kbps_since_last_connection_change_);
122 break; 163 break;
(...skipping 19 matching lines...) Expand all
142 break; 183 break;
143 case NetworkChangeNotifier::CONNECTION_NONE: 184 case NetworkChangeNotifier::CONNECTION_NONE:
144 UMA_HISTOGRAM_COUNTS("NQE.PeakKbps.None", 185 UMA_HISTOGRAM_COUNTS("NQE.PeakKbps.None",
145 peak_kbps_since_last_connection_change_); 186 peak_kbps_since_last_connection_change_);
146 break; 187 break;
147 case NetworkChangeNotifier::CONNECTION_BLUETOOTH: 188 case NetworkChangeNotifier::CONNECTION_BLUETOOTH:
148 UMA_HISTOGRAM_COUNTS("NQE.PeakKbps.Bluetooth", 189 UMA_HISTOGRAM_COUNTS("NQE.PeakKbps.Bluetooth",
149 peak_kbps_since_last_connection_change_); 190 peak_kbps_since_last_connection_change_);
150 break; 191 break;
151 default: 192 default:
152 NOTREACHED(); 193 NOTREACHED() << "Unexpected connection type = "
194 << current_connection_type_;
153 break; 195 break;
154 } 196 }
155 } 197 }
156 198
199 // Write the estimates of the previous network to the cache.
200 CacheNetworkQualityEstimate();
201
157 last_connection_change_ = base::TimeTicks::Now(); 202 last_connection_change_ = base::TimeTicks::Now();
158 bytes_read_since_last_connection_change_ = false; 203 bytes_read_since_last_connection_change_ = false;
159 peak_kbps_since_last_connection_change_ = 0; 204 peak_kbps_since_last_connection_change_ = 0;
160 current_connection_type_ = type; 205 current_connection_type_ = type;
206 current_network_name_ = GetCurrentNetworkName();
207
208 // Read any cached estimates for the new network.
209 ReadCachedNetworkQualityEstimate();
161 } 210 }
162 211
163 NetworkQuality NetworkQualityEstimator::GetEstimate() const { 212 NetworkQuality NetworkQualityEstimator::GetEstimate() const {
164 DCHECK(thread_checker_.CalledOnValidThread()); 213 DCHECK(thread_checker_.CalledOnValidThread());
165 214
166 if (!bytes_read_since_last_connection_change_) { 215 if (!bytes_read_since_last_connection_change_) {
167 return NetworkQuality(fastest_RTT_since_last_connection_change_, 0, 216 return NetworkQuality(fastest_RTT_since_last_connection_change_, 0,
168 peak_kbps_since_last_connection_change_, 0); 217 peak_kbps_since_last_connection_change_, 0);
169 } 218 }
170 if (!peak_kbps_since_last_connection_change_) { 219 if (!peak_kbps_since_last_connection_change_) {
171 return NetworkQuality(fastest_RTT_since_last_connection_change_, 0.1, 220 return NetworkQuality(fastest_RTT_since_last_connection_change_, 0.1,
172 peak_kbps_since_last_connection_change_, 0); 221 peak_kbps_since_last_connection_change_, 0);
173 } 222 }
174 return NetworkQuality(fastest_RTT_since_last_connection_change_, 0.1, 223 return NetworkQuality(fastest_RTT_since_last_connection_change_, 0.1,
175 peak_kbps_since_last_connection_change_, 0.1); 224 peak_kbps_since_last_connection_change_, 0.1);
176 } 225 }
177 226
227 std::string NetworkQualityEstimator::GetCurrentNetworkName() const {
228 DCHECK(thread_checker_.CalledOnValidThread());
229
230 if (current_connection_type_ ==
231 NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN ||
232 current_connection_type_ ==
233 NetworkChangeNotifier::ConnectionType::CONNECTION_NONE ||
234 current_connection_type_ ==
235 NetworkChangeNotifier::ConnectionType::CONNECTION_BLUETOOTH)
236 return std::string();
237
238 if (current_connection_type_ ==
239 NetworkChangeNotifier::ConnectionType::CONNECTION_ETHERNET) {
240 return "ethernet";
241 }
242
243 #if defined(OS_ANDROID)
244 if (current_connection_type_ ==
245 NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI)
246 return GetWifiSSID();
247 if (current_connection_type_ ==
248 NetworkChangeNotifier::ConnectionType::CONNECTION_2G ||
249 current_connection_type_ ==
250 NetworkChangeNotifier::ConnectionType::CONNECTION_3G ||
251 current_connection_type_ ==
252 NetworkChangeNotifier::ConnectionType::CONNECTION_4G)
253 return android::GetTelephonyNetworkOperator();
254 NOTREACHED() << "Unexpected connection type = " << current_connection_type_;
255 #endif // OS_ANDROID
256
257 return std::string();
258 }
259
260 bool NetworkQualityEstimator::ReadCachedNetworkQualityEstimate() {
261 DCHECK(thread_checker_.CalledOnValidThread());
262
263 if (current_network_name_ == "")
264 return false;
265
266 for (const auto& network_quality : cached_network_quality_) {
267 if (network_quality.connection_type != current_connection_type_ ||
268 network_quality.network_name != current_network_name_)
269 continue;
270
271 // TOOD(tbansal): Populate these values back into the median computing
272 // algorithm.
273 // Add UMA to record how frequently match happens.
274 // int64 median_kbps = network_quality.median_kbps;
275 // int64 median_rtt_msec = network_quality.median_rtt_milliseconds;
276 return true;
277 }
278
279 return false;
280 }
281
282 void NetworkQualityEstimator::CacheNetworkQualityEstimate() {
283 DCHECK(thread_checker_.CalledOnValidThread());
284
285 if (current_network_name_ == "")
286 return;
287
288 // TODO(tbansal): Following variables should be initialized using the median
289 /// values reported by NetworkQualityEstimator.
290 int median_kbps = 0;
291 int median_rtt_milliseconds = 0;
292
293 // If this network is already in the cache, overwrite that entry.
294 for (auto& network_quality : cached_network_quality_) {
295 if (network_quality.connection_type != current_connection_type_ ||
296 network_quality.network_name != current_network_name_)
297 continue;
298
299 network_quality.UpdateNetworkQuality(median_kbps, median_rtt_milliseconds);
300 return;
301 }
302
303 if (cached_network_quality_.size() < kMaximumNetworkQualityCacheSize) {
304 cached_network_quality_.push_back(
305 CachedNetworkQuality(current_connection_type_, current_network_name_,
306 median_kbps, median_rtt_milliseconds));
307 return;
308 }
309
310 DCHECK_EQ(kMaximumNetworkQualityCacheSize, cached_network_quality_.size());
311
312 // Overwrite the oldest entry.
313 int oldest_entry_index = 0;
314 for (size_t i = 0; i < cached_network_quality_.size(); ++i) {
315 if (cached_network_quality_[i].last_updated <
316 cached_network_quality_[oldest_entry_index].last_updated)
317 oldest_entry_index = i;
318 }
319
320 cached_network_quality_[oldest_entry_index] =
321 CachedNetworkQuality(current_connection_type_, current_network_name_,
322 median_kbps, median_rtt_milliseconds);
323
324 DCHECK_EQ(kMaximumNetworkQualityCacheSize, cached_network_quality_.size());
mmenke 2015/05/28 15:25:02 include base/logging.h for DCHECK and NOTREACHED.
tbansal1 2015/05/29 02:27:23 Done.
325 }
326
178 } // namespace net 327 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698