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

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: 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/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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698