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

Unified 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: Changes to make the tests work on Windows 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/base/network_quality_estimator.h ('k') | net/base/network_quality_estimator_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/base/network_quality_estimator.cc
diff --git a/net/base/network_quality_estimator.cc b/net/base/network_quality_estimator.cc
index 6415ee6e6d7eb36b47ab4fd568d3537283b27729..e864c7e1f4619501fb8ce7073545f6f4c3ab7752 100644
--- a/net/base/network_quality_estimator.cc
+++ b/net/base/network_quality_estimator.cc
@@ -4,6 +4,7 @@
#include "net/base/network_quality_estimator.h"
+#include <limits>
#include <string>
#include "base/logging.h"
@@ -13,6 +14,13 @@
#include "net/url_request/url_request.h"
#include "url/gurl.h"
+namespace {
+
+// Maximum number of observations that can be held in the ObservationBuffer.
+const size_t kMaximumObservationsBufferSize = 500;
+
+} // namespace
+
namespace net {
NetworkQualityEstimator::NetworkQualityEstimator()
@@ -24,7 +32,7 @@ NetworkQualityEstimator::NetworkQualityEstimator(
: allow_localhost_requests_(allow_local_host_requests_for_tests),
last_connection_change_(base::TimeTicks::Now()),
current_connection_type_(NetworkChangeNotifier::GetConnectionType()),
- bytes_read_since_last_connection_change_(false),
+ fastest_rtt_since_last_connection_change_(base::TimeDelta::Max()),
peak_kbps_since_last_connection_change_(0) {
static_assert(kMinRequestDurationMicroseconds > 0,
"Minimum request duration must be > 0");
@@ -36,10 +44,13 @@ NetworkQualityEstimator::~NetworkQualityEstimator() {
NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
}
-void NetworkQualityEstimator::NotifyDataReceived(const URLRequest& request,
- int64_t prefilter_bytes_read) {
+void NetworkQualityEstimator::NotifyDataReceived(
+ const URLRequest& request,
+ int64_t cumulative_prefilter_bytes_read,
+ int64_t prefiltered_bytes_read) {
DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK_GT(prefilter_bytes_read, 0);
+ DCHECK_GT(cumulative_prefilter_bytes_read, 0);
+ DCHECK_GT(prefiltered_bytes_read, 0);
if (!request.url().is_valid() ||
(!allow_localhost_requests_ && IsLocalhost(request.url().host())) ||
@@ -54,61 +65,77 @@ void NetworkQualityEstimator::NotifyDataReceived(const URLRequest& request,
base::TimeTicks now = base::TimeTicks::Now();
base::TimeDelta request_duration = now - request.creation_time();
DCHECK_GE(request_duration, base::TimeDelta());
- if (!bytes_read_since_last_connection_change_)
- fastest_RTT_since_last_connection_change_ = request_duration;
- bytes_read_since_last_connection_change_ = true;
- if (request_duration < fastest_RTT_since_last_connection_change_)
- fastest_RTT_since_last_connection_change_ = request_duration;
+ // Only add RTT observation if this is the first read for this response.
+ if (cumulative_prefilter_bytes_read == prefiltered_bytes_read) {
+ if (request_duration < fastest_rtt_since_last_connection_change_)
+ fastest_rtt_since_last_connection_change_ = request_duration;
+
+ rtt_msec_observations_.AddObservation(
+ Observation(request_duration.InMilliseconds(), now));
+ }
// Ignore tiny transfers which will not produce accurate rates.
// Ignore short duration transfers.
- if (prefilter_bytes_read >= kMinTransferSizeInBytes &&
+ if (cumulative_prefilter_bytes_read >= kMinTransferSizeInBytes &&
request_duration >=
base::TimeDelta::FromMicroseconds(kMinRequestDurationMicroseconds)) {
- uint64_t kbps = static_cast<uint64_t>(prefilter_bytes_read * 8 * 1000 /
- request_duration.InMicroseconds());
- if (kbps > peak_kbps_since_last_connection_change_)
- peak_kbps_since_last_connection_change_ = kbps;
+ double kbps_f = cumulative_prefilter_bytes_read * 8.0 / 1000.0 /
+ request_duration.InSecondsF();
+ DCHECK_GE(kbps_f, 0.0);
+
+ // Check overflow errors. This may happen if the kbpsF is more than
+ // 2 * 10^9 (= 2000 Gbps).
+ if (kbps_f >= std::numeric_limits<int32_t>::max())
+ kbps_f = std::numeric_limits<int32_t>::max() - 1;
+
+ int32_t kbps = static_cast<int32_t>(kbps_f);
+
+ if (kbps > 0) {
+ if (kbps > peak_kbps_since_last_connection_change_)
+ peak_kbps_since_last_connection_change_ = kbps;
+
+ kbps_observations_.AddObservation(Observation(kbps, now));
+ }
}
}
void NetworkQualityEstimator::OnConnectionTypeChanged(
NetworkChangeNotifier::ConnectionType type) {
DCHECK(thread_checker_.CalledOnValidThread());
- if (bytes_read_since_last_connection_change_) {
+ if (fastest_rtt_since_last_connection_change_ != base::TimeDelta::Max()) {
switch (current_connection_type_) {
case NetworkChangeNotifier::CONNECTION_UNKNOWN:
UMA_HISTOGRAM_TIMES("NQE.FastestRTT.Unknown",
- fastest_RTT_since_last_connection_change_);
+ fastest_rtt_since_last_connection_change_);
break;
case NetworkChangeNotifier::CONNECTION_ETHERNET:
UMA_HISTOGRAM_TIMES("NQE.FastestRTT.Ethernet",
- fastest_RTT_since_last_connection_change_);
+ fastest_rtt_since_last_connection_change_);
break;
case NetworkChangeNotifier::CONNECTION_WIFI:
UMA_HISTOGRAM_TIMES("NQE.FastestRTT.Wifi",
- fastest_RTT_since_last_connection_change_);
+ fastest_rtt_since_last_connection_change_);
break;
case NetworkChangeNotifier::CONNECTION_2G:
UMA_HISTOGRAM_TIMES("NQE.FastestRTT.2G",
- fastest_RTT_since_last_connection_change_);
+ fastest_rtt_since_last_connection_change_);
break;
case NetworkChangeNotifier::CONNECTION_3G:
UMA_HISTOGRAM_TIMES("NQE.FastestRTT.3G",
- fastest_RTT_since_last_connection_change_);
+ fastest_rtt_since_last_connection_change_);
break;
case NetworkChangeNotifier::CONNECTION_4G:
UMA_HISTOGRAM_TIMES("NQE.FastestRTT.4G",
- fastest_RTT_since_last_connection_change_);
+ fastest_rtt_since_last_connection_change_);
break;
case NetworkChangeNotifier::CONNECTION_NONE:
UMA_HISTOGRAM_TIMES("NQE.FastestRTT.None",
- fastest_RTT_since_last_connection_change_);
+ fastest_rtt_since_last_connection_change_);
break;
case NetworkChangeNotifier::CONNECTION_BLUETOOTH:
UMA_HISTOGRAM_TIMES("NQE.FastestRTT.Bluetooth",
- fastest_RTT_since_last_connection_change_);
+ fastest_rtt_since_last_connection_change_);
break;
default:
NOTREACHED();
@@ -157,24 +184,67 @@ void NetworkQualityEstimator::OnConnectionTypeChanged(
}
last_connection_change_ = base::TimeTicks::Now();
- bytes_read_since_last_connection_change_ = false;
peak_kbps_since_last_connection_change_ = 0;
+ fastest_rtt_since_last_connection_change_ = base::TimeDelta::Max();
+ kbps_observations_.Clear();
+ rtt_msec_observations_.Clear();
current_connection_type_ = type;
}
-NetworkQuality NetworkQualityEstimator::GetEstimate() const {
+NetworkQuality NetworkQualityEstimator::GetPeakEstimate() const {
DCHECK(thread_checker_.CalledOnValidThread());
- if (!bytes_read_since_last_connection_change_) {
- return NetworkQuality(fastest_RTT_since_last_connection_change_, 0,
- peak_kbps_since_last_connection_change_, 0);
- }
- if (!peak_kbps_since_last_connection_change_) {
- return NetworkQuality(fastest_RTT_since_last_connection_change_, 0.1,
- peak_kbps_since_last_connection_change_, 0);
- }
- return NetworkQuality(fastest_RTT_since_last_connection_change_, 0.1,
- peak_kbps_since_last_connection_change_, 0.1);
+ return NetworkQuality(fastest_rtt_since_last_connection_change_,
+ peak_kbps_since_last_connection_change_);
+}
+
+size_t NetworkQualityEstimator::GetMaximumObservationBufferSizeForTests()
+ const {
+ return kMaximumObservationsBufferSize;
+}
+
+bool NetworkQualityEstimator::VerifyBufferSizeForTests(
+ size_t expected_size) const {
+ return kbps_observations_.Size() == expected_size &&
+ rtt_msec_observations_.Size() == expected_size;
+}
+
+NetworkQualityEstimator::Observation::Observation(int32_t value,
+ base::TimeTicks timestamp)
+ : value(value), timestamp(timestamp) {
+ DCHECK_GE(value, 0);
+ DCHECK(!timestamp.is_null());
+}
+
+NetworkQualityEstimator::Observation::~Observation() {
+}
+
+NetworkQualityEstimator::ObservationBuffer::ObservationBuffer() {
+ static_assert(kMaximumObservationsBufferSize > 0U,
+ "Minimum size of observation buffer must be > 0");
+}
+
+NetworkQualityEstimator::ObservationBuffer::~ObservationBuffer() {
+}
+
+void NetworkQualityEstimator::ObservationBuffer::AddObservation(
+ const Observation& observation) {
+ DCHECK_LE(observations_.size(), kMaximumObservationsBufferSize);
+ // Evict the oldest element if the buffer is already full.
+ if (observations_.size() == kMaximumObservationsBufferSize)
+ observations_.pop_front();
+
+ observations_.push_back(observation);
+ DCHECK_LE(observations_.size(), kMaximumObservationsBufferSize);
+}
+
+size_t NetworkQualityEstimator::ObservationBuffer::Size() const {
+ return observations_.size();
+}
+
+void NetworkQualityEstimator::ObservationBuffer::Clear() {
+ observations_.clear();
+ DCHECK(observations_.empty());
}
} // namespace net
« no previous file with comments | « net/base/network_quality_estimator.h ('k') | net/base/network_quality_estimator_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698