Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 |
| 15 namespace net { | 16 namespace net { |
| 16 | 17 |
| 17 NetworkQualityEstimator::NetworkQualityEstimator() | 18 NetworkQualityEstimator::NetworkQualityEstimator() |
| 18 : NetworkQualityEstimator(false) { | 19 : NetworkQualityEstimator(false) { |
| 19 } | 20 } |
| 20 | 21 |
| 21 NetworkQualityEstimator::NetworkQualityEstimator( | 22 NetworkQualityEstimator::NetworkQualityEstimator( |
| 22 bool allow_local_host_requests_for_tests) | 23 bool allow_local_host_requests_for_tests) |
| 23 : allow_localhost_requests_(allow_local_host_requests_for_tests), | 24 : allow_localhost_requests_(allow_local_host_requests_for_tests), |
| 24 last_connection_change_(base::TimeTicks::Now()), | 25 last_connection_change_(base::TimeTicks::Now()), |
| 25 current_connection_type_(NetworkChangeNotifier::GetConnectionType()), | 26 current_connection_type_(NetworkChangeNotifier::GetConnectionType()), |
| 26 bytes_read_since_last_connection_change_(false), | 27 bytes_read_since_last_connection_change_(false), |
| 27 peak_kbps_since_last_connection_change_(0) { | 28 peak_kbps_since_last_connection_change_(0) { |
| 28 static_assert(kMinRequestDurationMicroseconds > 0, | 29 static_assert(kMinRequestDurationMicroseconds > 0, |
| 29 "Minimum request duration must be > 0"); | 30 "Minimum request duration must be > 0"); |
| 30 NetworkChangeNotifier::AddConnectionTypeObserver(this); | 31 NetworkChangeNotifier::AddConnectionTypeObserver(this); |
| 31 } | 32 } |
| 32 | 33 |
| 33 NetworkQualityEstimator::~NetworkQualityEstimator() { | 34 NetworkQualityEstimator::~NetworkQualityEstimator() { |
| 34 DCHECK(thread_checker_.CalledOnValidThread()); | 35 DCHECK(thread_checker_.CalledOnValidThread()); |
| 35 NetworkChangeNotifier::RemoveConnectionTypeObserver(this); | 36 NetworkChangeNotifier::RemoveConnectionTypeObserver(this); |
| 36 } | 37 } |
| 37 | 38 |
| 38 void NetworkQualityEstimator::NotifyDataReceived(const URLRequest& request, | 39 void NetworkQualityEstimator::NotifyDataReceived( |
| 39 int64_t prefilter_bytes_read) { | 40 const URLRequest& request, |
| 41 int64_t cummulative_prefilter_bytes_read, | |
| 42 int64_t prefiltered_bytes_read) { | |
| 40 DCHECK(thread_checker_.CalledOnValidThread()); | 43 DCHECK(thread_checker_.CalledOnValidThread()); |
| 41 DCHECK_GT(prefilter_bytes_read, 0); | 44 DCHECK_GT(cummulative_prefilter_bytes_read, 0); |
| 45 DCHECK_GT(prefiltered_bytes_read, 0); | |
| 42 | 46 |
| 43 if (!request.url().is_valid() || | 47 if (!request.url().is_valid() || |
| 44 (!allow_localhost_requests_ && IsLocalhost(request.url().host())) || | 48 (!allow_localhost_requests_ && IsLocalhost(request.url().host())) || |
| 45 !request.url().SchemeIsHTTPOrHTTPS() || | 49 !request.url().SchemeIsHTTPOrHTTPS() || |
| 46 // Verify that response headers are received, so it can be ensured that | 50 // Verify that response headers are received, so it can be ensured that |
| 47 // response is not cached. | 51 // response is not cached. |
| 48 request.response_info().response_time.is_null() || request.was_cached()) | 52 request.response_info().response_time.is_null() || request.was_cached() || |
| 53 request.creation_time() < last_connection_change_) { | |
| 49 return; | 54 return; |
| 55 } | |
| 50 | 56 |
| 51 base::TimeTicks now = base::TimeTicks::Now(); | 57 base::TimeTicks now = base::TimeTicks::Now(); |
| 52 base::TimeDelta request_duration = now - request.creation_time(); | 58 base::TimeDelta request_duration = now - request.creation_time(); |
| 53 DCHECK_GE(request_duration, base::TimeDelta()); | 59 DCHECK_GE(request_duration, base::TimeDelta()); |
| 54 if (!bytes_read_since_last_connection_change_) | 60 if (!bytes_read_since_last_connection_change_) |
| 55 fastest_RTT_since_last_connection_change_ = request_duration; | 61 fastest_RTT_since_last_connection_change_ = request_duration; |
| 56 | 62 |
| 57 bytes_read_since_last_connection_change_ = true; | 63 bytes_read_since_last_connection_change_ = true; |
| 58 if (request_duration < fastest_RTT_since_last_connection_change_) | 64 if (request_duration < fastest_RTT_since_last_connection_change_) |
| 59 fastest_RTT_since_last_connection_change_ = request_duration; | 65 fastest_RTT_since_last_connection_change_ = request_duration; |
| 60 | 66 |
| 67 // Only add RTT sample if this is the first read for this response. | |
| 68 if (cummulative_prefilter_bytes_read == prefiltered_bytes_read) | |
| 69 rtt_msec_.AddSample(request_duration.InMilliseconds()); | |
| 70 | |
| 61 // Ignore tiny transfers which will not produce accurate rates. | 71 // Ignore tiny transfers which will not produce accurate rates. |
| 62 // Ignore short duration transfers. | 72 // Ignore short duration transfers. |
| 63 if (prefilter_bytes_read >= kMinTransferSizeInBytes && | 73 if (cummulative_prefilter_bytes_read >= kMinTransferSizeInBytes && |
| 64 request_duration >= | 74 request_duration >= |
| 65 base::TimeDelta::FromMicroseconds(kMinRequestDurationMicroseconds) && | 75 base::TimeDelta::FromMicroseconds(kMinRequestDurationMicroseconds)) { |
| 66 request.creation_time() > last_connection_change_) { | 76 uint64_t kbps = |
| 67 uint64_t kbps = static_cast<uint64_t>(prefilter_bytes_read * 8 * 1000 / | 77 static_cast<uint64_t>(cummulative_prefilter_bytes_read * 8 * 1000 / |
| 68 request_duration.InMicroseconds()); | 78 request_duration.InMicroseconds()); |
| 69 if (kbps > peak_kbps_since_last_connection_change_) | 79 if (kbps > peak_kbps_since_last_connection_change_) |
| 70 peak_kbps_since_last_connection_change_ = kbps; | 80 peak_kbps_since_last_connection_change_ = kbps; |
| 81 | |
| 82 kbps_.AddSample(kbps); | |
| 71 } | 83 } |
| 72 } | 84 } |
| 73 | 85 |
| 74 void NetworkQualityEstimator::OnConnectionTypeChanged( | 86 void NetworkQualityEstimator::OnConnectionTypeChanged( |
| 75 NetworkChangeNotifier::ConnectionType type) { | 87 NetworkChangeNotifier::ConnectionType type) { |
| 76 DCHECK(thread_checker_.CalledOnValidThread()); | 88 DCHECK(thread_checker_.CalledOnValidThread()); |
| 77 if (bytes_read_since_last_connection_change_) { | 89 if (bytes_read_since_last_connection_change_) { |
| 78 switch (current_connection_type_) { | 90 switch (current_connection_type_) { |
| 79 case NetworkChangeNotifier::CONNECTION_UNKNOWN: | 91 case NetworkChangeNotifier::CONNECTION_UNKNOWN: |
| 80 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.Unknown", | 92 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.Unknown", |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 153 break; | 165 break; |
| 154 } | 166 } |
| 155 } | 167 } |
| 156 | 168 |
| 157 last_connection_change_ = base::TimeTicks::Now(); | 169 last_connection_change_ = base::TimeTicks::Now(); |
| 158 bytes_read_since_last_connection_change_ = false; | 170 bytes_read_since_last_connection_change_ = false; |
| 159 peak_kbps_since_last_connection_change_ = 0; | 171 peak_kbps_since_last_connection_change_ = 0; |
| 160 current_connection_type_ = type; | 172 current_connection_type_ = type; |
| 161 } | 173 } |
| 162 | 174 |
| 163 NetworkQuality NetworkQualityEstimator::GetEstimate() const { | 175 NetworkQuality NetworkQualityEstimator::GetPeakEstimate() const { |
| 164 DCHECK(thread_checker_.CalledOnValidThread()); | 176 DCHECK(thread_checker_.CalledOnValidThread()); |
| 165 | 177 |
| 166 if (!bytes_read_since_last_connection_change_) { | 178 if (!bytes_read_since_last_connection_change_) { |
| 167 return NetworkQuality(fastest_RTT_since_last_connection_change_, 0, | 179 return NetworkQuality(fastest_RTT_since_last_connection_change_, 0, |
| 168 peak_kbps_since_last_connection_change_, 0); | 180 peak_kbps_since_last_connection_change_, 0); |
| 169 } | 181 } |
| 170 if (!peak_kbps_since_last_connection_change_) { | 182 if (!peak_kbps_since_last_connection_change_) { |
| 171 return NetworkQuality(fastest_RTT_since_last_connection_change_, 0.1, | 183 return NetworkQuality(fastest_RTT_since_last_connection_change_, 0.1, |
| 172 peak_kbps_since_last_connection_change_, 0); | 184 peak_kbps_since_last_connection_change_, 0); |
| 173 } | 185 } |
| 174 return NetworkQuality(fastest_RTT_since_last_connection_change_, 0.1, | 186 return NetworkQuality(fastest_RTT_since_last_connection_change_, 0.1, |
| 175 peak_kbps_since_last_connection_change_, 0.1); | 187 peak_kbps_since_last_connection_change_, 0.1); |
|
mmenke
2015/06/03 18:31:39
This seems a bit silly. Suggest just always retur
tbansal1
2015/06/05 01:50:08
Done.
| |
| 176 } | 188 } |
| 177 | 189 |
| 190 NetworkQualityEstimator::Sample::Sample(int value) | |
| 191 : value_(value), timestamp_(base::TimeTicks::Now()) { | |
| 192 DCHECK_GE(value_, 0); | |
| 193 } | |
| 194 | |
| 195 NetworkQualityEstimator::Sample::~Sample() { | |
| 196 } | |
| 197 | |
| 198 NetworkQualityEstimator::RingBuffer::RingBuffer() { | |
| 199 DCHECK_GT(kMaximumSamples, 0U); | |
|
mmenke
2015/06/03 18:31:39
If you think this is necessary, should use static_
tbansal1
2015/06/05 01:50:08
Done.
| |
| 200 } | |
| 201 | |
| 202 NetworkQualityEstimator::RingBuffer::~RingBuffer() { | |
| 203 } | |
| 204 | |
| 205 void NetworkQualityEstimator::RingBuffer::AddSample(int value) { | |
| 206 DCHECK_LE(samples_.size(), kMaximumSamples); | |
| 207 // Pop the oldest element if the buffer is already full. | |
| 208 if (samples_.size() >= kMaximumSamples) | |
| 209 samples_.pop_front(); | |
| 210 | |
| 211 samples_.push_back(Sample(value)); | |
| 212 DCHECK_LE(samples_.size(), kMaximumSamples); | |
| 213 } | |
| 214 | |
| 178 } // namespace net | 215 } // namespace net |
| OLD | NEW |