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

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: Addressed comments and reorganized tests 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 "base/logging.h"
8
9 #include "base/metrics/histogram.h" 8 #include "base/metrics/histogram.h"
10 #include "net/base/net_util.h" 9 #include "net/base/net_util.h"
11 #include "net/base/network_quality.h" 10 #include "net/base/network_quality.h"
12 #include "net/url_request/url_request.h" 11 #include "net/url_request/url_request.h"
13 #include "url/gurl.h" 12 #include "url/gurl.h"
14 13
14 #if defined(OS_ANDROID)
15 #include "net/android/network_library.h"
16 #endif // OS_ANDROID
17
18 namespace {
19
20 // Maximum size of the cache that holds network quality estimates.
21 // Smaller size may reduce the cache hit rate due to frequent evictions.
22 // Larger size may affect performance.
23 const uint32_t kMaximumNetworkQualityCacheSize = 5;
24
25 } // namespace
26
15 namespace net { 27 namespace net {
16 28
17 NetworkQualityEstimator::NetworkQualityEstimator() 29 NetworkQualityEstimator::NetworkQualityEstimator()
18 : NetworkQualityEstimator(false) { 30 : NetworkQualityEstimator(false) {
19 } 31 }
20 32
21 NetworkQualityEstimator::NetworkQualityEstimator( 33 NetworkQualityEstimator::NetworkQualityEstimator(
22 bool allow_local_host_requests_for_tests) 34 bool allow_local_host_requests_for_tests)
23 : allow_localhost_requests_(allow_local_host_requests_for_tests), 35 : allow_localhost_requests_(allow_local_host_requests_for_tests),
24 last_connection_change_(base::TimeTicks::Now()), 36 last_connection_change_(base::TimeTicks::Now()),
25 current_connection_type_(NetworkChangeNotifier::GetConnectionType()), 37 current_connection_type_(NetworkChangeNotifier::GetConnectionType()),
26 bytes_read_since_last_connection_change_(false), 38 bytes_read_since_last_connection_change_(false),
27 peak_kbps_since_last_connection_change_(0) { 39 peak_kbps_since_last_connection_change_(0) {
28 static_assert(kMinRequestDurationMicroseconds > 0, 40 static_assert(kMinRequestDurationMicroseconds > 0,
29 "Minimum request duration must be > 0"); 41 "Minimum request duration must be > 0");
42 static_assert(kMaximumNetworkQualityCacheSize > 0,
43 "Size of the network quality cache must be > 0");
30 NetworkChangeNotifier::AddConnectionTypeObserver(this); 44 NetworkChangeNotifier::AddConnectionTypeObserver(this);
45 UpdateCurrentNetworkName();
31 } 46 }
32 47
33 NetworkQualityEstimator::~NetworkQualityEstimator() { 48 NetworkQualityEstimator::~NetworkQualityEstimator() {
34 DCHECK(thread_checker_.CalledOnValidThread()); 49 DCHECK(thread_checker_.CalledOnValidThread());
35 NetworkChangeNotifier::RemoveConnectionTypeObserver(this); 50 NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
36 } 51 }
37 52
38 void NetworkQualityEstimator::NotifyDataReceived(const URLRequest& request, 53 void NetworkQualityEstimator::NotifyDataReceived(const URLRequest& request,
39 int64_t prefilter_bytes_read) { 54 int64_t prefilter_bytes_read) {
40 DCHECK(thread_checker_.CalledOnValidThread()); 55 DCHECK(thread_checker_.CalledOnValidThread());
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
102 break; 117 break;
103 case NetworkChangeNotifier::CONNECTION_NONE: 118 case NetworkChangeNotifier::CONNECTION_NONE:
104 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.None", 119 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.None",
105 fastest_RTT_since_last_connection_change_); 120 fastest_RTT_since_last_connection_change_);
106 break; 121 break;
107 case NetworkChangeNotifier::CONNECTION_BLUETOOTH: 122 case NetworkChangeNotifier::CONNECTION_BLUETOOTH:
108 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.Bluetooth", 123 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.Bluetooth",
109 fastest_RTT_since_last_connection_change_); 124 fastest_RTT_since_last_connection_change_);
110 break; 125 break;
111 default: 126 default:
112 NOTREACHED(); 127 NOTREACHED() << "Unexpected connection type = "
128 << current_connection_type_;
113 break; 129 break;
114 } 130 }
115 } 131 }
116 132
117 if (peak_kbps_since_last_connection_change_) { 133 if (peak_kbps_since_last_connection_change_) {
118 switch (current_connection_type_) { 134 switch (current_connection_type_) {
119 case NetworkChangeNotifier::CONNECTION_UNKNOWN: 135 case NetworkChangeNotifier::CONNECTION_UNKNOWN:
120 UMA_HISTOGRAM_COUNTS("NQE.PeakKbps.Unknown", 136 UMA_HISTOGRAM_COUNTS("NQE.PeakKbps.Unknown",
121 peak_kbps_since_last_connection_change_); 137 peak_kbps_since_last_connection_change_);
122 break; 138 break;
(...skipping 19 matching lines...) Expand all
142 break; 158 break;
143 case NetworkChangeNotifier::CONNECTION_NONE: 159 case NetworkChangeNotifier::CONNECTION_NONE:
144 UMA_HISTOGRAM_COUNTS("NQE.PeakKbps.None", 160 UMA_HISTOGRAM_COUNTS("NQE.PeakKbps.None",
145 peak_kbps_since_last_connection_change_); 161 peak_kbps_since_last_connection_change_);
146 break; 162 break;
147 case NetworkChangeNotifier::CONNECTION_BLUETOOTH: 163 case NetworkChangeNotifier::CONNECTION_BLUETOOTH:
148 UMA_HISTOGRAM_COUNTS("NQE.PeakKbps.Bluetooth", 164 UMA_HISTOGRAM_COUNTS("NQE.PeakKbps.Bluetooth",
149 peak_kbps_since_last_connection_change_); 165 peak_kbps_since_last_connection_change_);
150 break; 166 break;
151 default: 167 default:
152 NOTREACHED(); 168 NOTREACHED() << "Unexpected connection type = "
169 << current_connection_type_;
153 break; 170 break;
154 } 171 }
155 } 172 }
156 173
174 // Write the estimates of the previous network to the cache.
175 CacheNetworkQualityEstimate();
176
157 last_connection_change_ = base::TimeTicks::Now(); 177 last_connection_change_ = base::TimeTicks::Now();
158 bytes_read_since_last_connection_change_ = false; 178 bytes_read_since_last_connection_change_ = false;
159 peak_kbps_since_last_connection_change_ = 0; 179 peak_kbps_since_last_connection_change_ = 0;
160 current_connection_type_ = type; 180 current_connection_type_ = type;
181 UpdateCurrentNetworkName();
182
183 // Read any cached estimates for the new network.
184 ReadCachedNetworkQualityEstimate();
185 }
186
187 uint32_t NetworkQualityEstimator::GetCacheSizeForTests() const {
188 return cached_network_quality_.size();
189 }
190
191 void NetworkQualityEstimator::SetCurrentNetworkNameForTests(
192 std::string network_name) {
193 current_network_name_ = network_name;
161 } 194 }
162 195
163 NetworkQuality NetworkQualityEstimator::GetEstimate() const { 196 NetworkQuality NetworkQualityEstimator::GetEstimate() 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 void NetworkQualityEstimator::UpdateCurrentNetworkName() {
212 DCHECK(thread_checker_.CalledOnValidThread());
213
214 current_network_name_ = std::string();
215 if (current_connection_type_ ==
216 NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN ||
bengr 2015/05/29 17:38:09 Using a switch might be cleaner.
tbansal1 2015/05/29 19:13:36 Done.
217 current_connection_type_ ==
218 NetworkChangeNotifier::ConnectionType::CONNECTION_NONE ||
219 current_connection_type_ ==
220 NetworkChangeNotifier::ConnectionType::CONNECTION_BLUETOOTH) {
221 return;
222 }
223
224 if (current_connection_type_ ==
225 NetworkChangeNotifier::ConnectionType::CONNECTION_ETHERNET) {
226 current_network_name_ = "ethernet";
227 return;
228 }
229
230 #if defined(OS_ANDROID)
231 if (current_connection_type_ ==
232 NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI)
233 return GetWifiSSID();
234 if (current_connection_type_ ==
235 NetworkChangeNotifier::ConnectionType::CONNECTION_2G ||
236 current_connection_type_ ==
237 NetworkChangeNotifier::ConnectionType::CONNECTION_3G ||
238 current_connection_type_ ==
239 NetworkChangeNotifier::ConnectionType::CONNECTION_4G) {
240 current_network_name_ = android::GetTelephonyNetworkOperator();
241 return;
242 }
243 NOTREACHED() << "Unexpected connection type = " << current_connection_type_;
244 #endif // OS_ANDROID
245 }
246
247 bool NetworkQualityEstimator::ReadCachedNetworkQualityEstimate() {
248 DCHECK(thread_checker_.CalledOnValidThread());
249
250 if (current_network_name_ == "")
bengr 2015/05/29 17:38:09 if (current_network_name_.empty())
tbansal1 2015/05/29 19:13:36 Done.
251 return false;
252
253 for (const auto& network_quality : cached_network_quality_) {
254 if (!network_quality.MatchesNetwork(current_connection_type_,
255 current_network_name_))
256 continue;
bengr 2015/05/29 17:38:09 Add curly braces.
tbansal1 2015/05/29 19:13:36 Done.
257
258 // TOOD(tbansal): Populate these values back into the median computing
bengr 2015/05/29 17:38:09 Why are you not doing this in this CL?
tbansal1 2015/05/29 19:13:36 I need to populate these values back into Circular
259 // algorithm.
260 // Add UMA to record how frequently match happens.
261 // int64 median_kbps = network_quality.median_kbps;
262 // int64 median_rtt_msec = network_quality.median_rtt_milliseconds;
263 return true;
264 }
265
266 return false;
267 }
268
269 void NetworkQualityEstimator::CacheNetworkQualityEstimate() {
270 DCHECK(thread_checker_.CalledOnValidThread());
271
272 if (current_network_name_ == "")
bengr 2015/05/29 17:38:09 current_network_name_.empty()
tbansal1 2015/05/29 19:13:36 Done.
273 return;
274
275 // TODO(tbansal): Following variables should be initialized using the median
276 /// values reported by NetworkQualityEstimator.
277 int median_kbps = 0;
278 int median_rtt_milliseconds = 0;
279
280 // If this network is already in the cache, overwrite that entry.
281 for (auto& network_quality : cached_network_quality_) {
282 if (!network_quality.MatchesNetwork(current_connection_type_,
283 current_network_name_))
284 continue;
bengr 2015/05/29 17:38:09 Add curly braces.
tbansal1 2015/05/29 19:13:36 Done.
285
286 network_quality.UpdateNetworkQuality(median_kbps, median_rtt_milliseconds);
287 return;
288 }
289
290 if (cached_network_quality_.size() < kMaximumNetworkQualityCacheSize) {
291 cached_network_quality_.push_back(
292 CachedNetworkQuality(current_connection_type_, current_network_name_,
293 median_kbps, median_rtt_milliseconds));
294 return;
295 }
296
297 DCHECK_EQ(kMaximumNetworkQualityCacheSize, cached_network_quality_.size());
298
299 // Overwrite the oldest entry.
bengr 2015/05/29 17:38:09 I guess this is ok, but how often will this code b
tbansal1 2015/05/29 19:13:36 If we write the in-memory cache to prefs, 25 still
300 int oldest_entry_index = 0;
301 for (size_t i = 0; i < cached_network_quality_.size(); ++i) {
302 if (cached_network_quality_[i].last_updated_ <
303 cached_network_quality_[oldest_entry_index].last_updated_)
304 oldest_entry_index = i;
305 }
306
307 cached_network_quality_[oldest_entry_index] =
308 CachedNetworkQuality(current_connection_type_, current_network_name_,
309 median_kbps, median_rtt_milliseconds);
310
311 DCHECK_EQ(kMaximumNetworkQualityCacheSize, cached_network_quality_.size());
312 }
313
178 } // namespace net 314 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698