Skip to content

Commit

Permalink
NQE miscellaneous clean ups
Browse files Browse the repository at this point in the history
GetRTTEstimateInternal now takes a list of observation
sources as a parameter. Observations from these sources are
discarded when computing performance metrics. This will
help when adding API that returns median RTT at the
transport layer.

Condensed histogram code

Change some of the code in n_q_e.cc and some tests so that
they call NQE's public APIs.

BUG=498380

Review URL: https://codereview.chromium.org/1892273002

Cr-Commit-Position: refs/heads/master@{#389555}
  • Loading branch information
tbansal authored and Commit bot committed Apr 25, 2016
1 parent dc1f648 commit e481a6c
Show file tree
Hide file tree
Showing 3 changed files with 165 additions and 229 deletions.
181 changes: 57 additions & 124 deletions net/base/network_quality_estimator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -405,9 +405,16 @@ void NetworkQualityEstimator::NotifyHeadersReceived(const URLRequest& request) {

// Update |estimated_median_network_quality_| if this is a main frame request.
if (request.load_flags() & LOAD_MAIN_FRAME) {
estimated_median_network_quality_ = NetworkQuality(
GetURLRequestRTTEstimateInternal(base::TimeTicks(), 50),
GetDownlinkThroughputKbpsEstimateInternal(base::TimeTicks(), 50));
base::TimeDelta rtt;
if (!GetURLRequestRTTEstimate(&rtt))
rtt = InvalidRTT();

int32_t downstream_throughput_kbps;
if (!GetDownlinkThroughputKbpsEstimate(&downstream_throughput_kbps))
downstream_throughput_kbps = kInvalidThroughput;

estimated_median_network_quality_ =
NetworkQuality(rtt, downstream_throughput_kbps);
}

base::TimeTicks now = base::TimeTicks::Now();
Expand Down Expand Up @@ -600,104 +607,34 @@ void NetworkQualityEstimator::OnConnectionTypeChanged(
NetworkChangeNotifier::ConnectionType type) {
DCHECK(thread_checker_.CalledOnValidThread());
if (peak_network_quality_.rtt() != InvalidRTT()) {
switch (current_network_id_.type) {
case NetworkChangeNotifier::CONNECTION_UNKNOWN:
UMA_HISTOGRAM_TIMES("NQE.FastestRTT.Unknown",
peak_network_quality_.rtt());
break;
case NetworkChangeNotifier::CONNECTION_ETHERNET:
UMA_HISTOGRAM_TIMES("NQE.FastestRTT.Ethernet",
peak_network_quality_.rtt());
break;
case NetworkChangeNotifier::CONNECTION_WIFI:
UMA_HISTOGRAM_TIMES("NQE.FastestRTT.Wifi", peak_network_quality_.rtt());
break;
case NetworkChangeNotifier::CONNECTION_2G:
UMA_HISTOGRAM_TIMES("NQE.FastestRTT.2G", peak_network_quality_.rtt());
break;
case NetworkChangeNotifier::CONNECTION_3G:
UMA_HISTOGRAM_TIMES("NQE.FastestRTT.3G", peak_network_quality_.rtt());
break;
case NetworkChangeNotifier::CONNECTION_4G:
UMA_HISTOGRAM_TIMES("NQE.FastestRTT.4G", peak_network_quality_.rtt());
break;
case NetworkChangeNotifier::CONNECTION_NONE:
UMA_HISTOGRAM_TIMES("NQE.FastestRTT.None", peak_network_quality_.rtt());
break;
case NetworkChangeNotifier::CONNECTION_BLUETOOTH:
UMA_HISTOGRAM_TIMES("NQE.FastestRTT.Bluetooth",
peak_network_quality_.rtt());
break;
default:
NOTREACHED() << "Unexpected connection type = "
<< current_network_id_.type;
break;
}
base::HistogramBase* rtt_histogram =
GetHistogram("FastestRTT.", current_network_id_.type, 10 * 1000);
rtt_histogram->Add(peak_network_quality_.rtt().InMilliseconds());
}

if (peak_network_quality_.downstream_throughput_kbps() !=
kInvalidThroughput) {
switch (current_network_id_.type) {
case NetworkChangeNotifier::CONNECTION_UNKNOWN:
UMA_HISTOGRAM_COUNTS(
"NQE.PeakKbps.Unknown",
peak_network_quality_.downstream_throughput_kbps());
break;
case NetworkChangeNotifier::CONNECTION_ETHERNET:
UMA_HISTOGRAM_COUNTS(
"NQE.PeakKbps.Ethernet",
peak_network_quality_.downstream_throughput_kbps());
break;
case NetworkChangeNotifier::CONNECTION_WIFI:
UMA_HISTOGRAM_COUNTS(
"NQE.PeakKbps.Wifi",
peak_network_quality_.downstream_throughput_kbps());
break;
case NetworkChangeNotifier::CONNECTION_2G:
UMA_HISTOGRAM_COUNTS(
"NQE.PeakKbps.2G",
peak_network_quality_.downstream_throughput_kbps());
break;
case NetworkChangeNotifier::CONNECTION_3G:
UMA_HISTOGRAM_COUNTS(
"NQE.PeakKbps.3G",
peak_network_quality_.downstream_throughput_kbps());
break;
case NetworkChangeNotifier::CONNECTION_4G:
UMA_HISTOGRAM_COUNTS(
"NQE.PeakKbps.4G",
peak_network_quality_.downstream_throughput_kbps());
break;
case NetworkChangeNotifier::CONNECTION_NONE:
UMA_HISTOGRAM_COUNTS(
"NQE.PeakKbps.None",
peak_network_quality_.downstream_throughput_kbps());
break;
case NetworkChangeNotifier::CONNECTION_BLUETOOTH:
UMA_HISTOGRAM_COUNTS(
"NQE.PeakKbps.Bluetooth",
peak_network_quality_.downstream_throughput_kbps());
break;
default:
NOTREACHED() << "Unexpected connection type = "
<< current_network_id_.type;
break;
}
base::HistogramBase* downstream_throughput_histogram =
GetHistogram("PeakKbps.", current_network_id_.type, 1000 * 1000);
downstream_throughput_histogram->Add(
peak_network_quality_.downstream_throughput_kbps());
}

base::TimeDelta rtt = GetURLRequestRTTEstimateInternal(base::TimeTicks(), 50);
if (rtt != InvalidRTT()) {
base::TimeDelta rtt;
if (GetURLRequestRTTEstimate(&rtt)) {
// Add the 50th percentile value.
base::HistogramBase* rtt_percentile =
GetHistogram("RTT.Percentile50.", current_network_id_.type,
10 * 1000); // 10 seconds
GetHistogram("RTT.Percentile50.", current_network_id_.type, 10 * 1000);
rtt_percentile->Add(rtt.InMilliseconds());

// Add the remaining percentile values.
static const int kPercentiles[] = {0, 10, 90, 100};
std::vector<ObservationSource> disallowed_observation_sources;
disallowed_observation_sources.push_back(TCP);
disallowed_observation_sources.push_back(QUIC);
for (size_t i = 0; i < arraysize(kPercentiles); ++i) {
rtt =
GetURLRequestRTTEstimateInternal(base::TimeTicks(), kPercentiles[i]);
rtt = GetRTTEstimateInternal(disallowed_observation_sources,
base::TimeTicks(), kPercentiles[i]);

rtt_percentile = GetHistogram(
"RTT.Percentile" + base::IntToString(kPercentiles[i]) + ".",
Expand Down Expand Up @@ -774,23 +711,17 @@ NetworkQualityEstimator::GetEffectiveConnectionType() const {
bool NetworkQualityEstimator::GetURLRequestRTTEstimate(
base::TimeDelta* rtt) const {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(rtt);
if (rtt_observations_.Size() == 0) {
*rtt = InvalidRTT();
return false;
}
*rtt = GetURLRequestRTTEstimateInternal(base::TimeTicks(), 50);
std::vector<ObservationSource> disallowed_observation_sources;
disallowed_observation_sources.push_back(TCP);
disallowed_observation_sources.push_back(QUIC);
*rtt = GetRTTEstimateInternal(disallowed_observation_sources,
base::TimeTicks(), 50);
return (*rtt != InvalidRTT());
}

bool NetworkQualityEstimator::GetDownlinkThroughputKbpsEstimate(
int32_t* kbps) const {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(kbps);
if (downstream_throughput_kbps_observations_.Size() == 0) {
*kbps = kInvalidThroughput;
return false;
}
*kbps = GetDownlinkThroughputKbpsEstimateInternal(base::TimeTicks(), 50);
return (*kbps != kInvalidThroughput);
}
Expand All @@ -799,16 +730,18 @@ bool NetworkQualityEstimator::GetRecentURLRequestRTTMedian(
const base::TimeTicks& begin_timestamp,
base::TimeDelta* rtt) const {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(rtt);
*rtt = GetURLRequestRTTEstimateInternal(begin_timestamp, 50);
std::vector<ObservationSource> disallowed_observation_sources;
disallowed_observation_sources.push_back(TCP);
disallowed_observation_sources.push_back(QUIC);
*rtt = GetRTTEstimateInternal(disallowed_observation_sources, begin_timestamp,
50);
return (*rtt != InvalidRTT());
}

bool NetworkQualityEstimator::GetRecentMedianDownlinkThroughputKbps(
const base::TimeTicks& begin_timestamp,
int32_t* kbps) const {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(kbps);
*kbps = GetDownlinkThroughputKbpsEstimateInternal(begin_timestamp, 50);
return (*kbps != kInvalidThroughput);
}
Expand All @@ -826,41 +759,35 @@ NetworkQualityEstimator::ObservationBuffer<ValueType>::ObservationBuffer(
template <typename ValueType>
NetworkQualityEstimator::ObservationBuffer<ValueType>::~ObservationBuffer() {}

base::TimeDelta NetworkQualityEstimator::GetURLRequestRTTEstimateInternal(
base::TimeDelta NetworkQualityEstimator::GetRTTEstimateInternal(
const std::vector<ObservationSource>& disallowed_observation_sources,
const base::TimeTicks& begin_timestamp,
int percentile) const {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK_GE(percentile, 0);
DCHECK_LE(percentile, 100);
if (rtt_observations_.Size() == 0)
return InvalidRTT();

// RTT observations are sorted by duration from shortest to longest, thus
// a higher percentile RTT will have a longer RTT than a lower percentile.
base::TimeDelta rtt = InvalidRTT();
std::vector<ObservationSource> disallowed_observation_sources;
disallowed_observation_sources.push_back(TCP);
disallowed_observation_sources.push_back(QUIC);
rtt_observations_.GetPercentile(begin_timestamp, &rtt, percentile,
disallowed_observation_sources);
if (!rtt_observations_.GetPercentile(begin_timestamp, &rtt, percentile,
disallowed_observation_sources)) {
return InvalidRTT();
}
return rtt;
}

int32_t NetworkQualityEstimator::GetDownlinkThroughputKbpsEstimateInternal(
const base::TimeTicks& begin_timestamp,
int percentile) const {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK_GE(percentile, 0);
DCHECK_LE(percentile, 100);
if (downstream_throughput_kbps_observations_.Size() == 0)
return kInvalidThroughput;

// Throughput observations are sorted by kbps from slowest to fastest,
// thus a higher percentile throughput will be faster than a lower one.
int32_t kbps = kInvalidThroughput;
downstream_throughput_kbps_observations_.GetPercentile(
begin_timestamp, &kbps, 100 - percentile,
std::vector<ObservationSource>());
if (!downstream_throughput_kbps_observations_.GetPercentile(
begin_timestamp, &kbps, 100 - percentile,
std::vector<ObservationSource>())) {
return kInvalidThroughput;
}
return kbps;
}

Expand Down Expand Up @@ -909,6 +836,9 @@ bool NetworkQualityEstimator::ObservationBuffer<ValueType>::GetPercentile(
const std::vector<ObservationSource>& disallowed_observation_sources)
const {
DCHECK(result);
DCHECK_GE(percentile, 0);
DCHECK_LE(percentile, 100);

// Stores WeightedObservation in increasing order of value.
std::vector<WeightedObservation<ValueType>> weighted_observations;

Expand Down Expand Up @@ -1111,14 +1041,17 @@ void NetworkQualityEstimator::CacheNetworkQualityEstimate() {
if (current_network_id_.id.empty())
return;

NetworkQuality network_quality = NetworkQuality(
GetURLRequestRTTEstimateInternal(base::TimeTicks(), 50),
GetDownlinkThroughputKbpsEstimateInternal(base::TimeTicks(), 50));
if (network_quality.rtt() == InvalidRTT() ||
network_quality.downstream_throughput_kbps() == kInvalidThroughput) {
base::TimeDelta rtt = InvalidRTT();
int32_t downlink_throughput_kbps = kInvalidThroughput;

if (!GetURLRequestRTTEstimate(&rtt) ||
!GetDownlinkThroughputKbpsEstimate(&downlink_throughput_kbps)) {
return;
}

NetworkQuality network_quality =
NetworkQuality(rtt, downlink_throughput_kbps);

if (cached_network_qualities_.size() == kMaximumNetworkQualityCacheSize) {
// Remove the oldest entry.
CachedNetworkQualities::iterator oldest_entry_iterator =
Expand Down
31 changes: 15 additions & 16 deletions net/base/network_quality_estimator.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <string>
#include <tuple>

#include "base/compiler_specific.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
Expand Down Expand Up @@ -161,7 +162,8 @@ class NET_EXPORT_PRIVATE NetworkQualityEstimator
// the HTTP layer measures the time from when the request was sent (this
// happens after the connection is established) to the time when the response
// headers were received.
virtual bool GetURLRequestRTTEstimate(base::TimeDelta* rtt) const;
virtual bool GetURLRequestRTTEstimate(base::TimeDelta* rtt) const
WARN_UNUSED_RESULT;

// Returns true if downlink throughput is available and sets |kbps| to
// estimated downlink throughput (in kilobits per second).
Expand All @@ -184,15 +186,15 @@ class NET_EXPORT_PRIVATE NetworkQualityEstimator
// received.
virtual bool GetRecentURLRequestRTTMedian(
const base::TimeTicks& begin_timestamp,
base::TimeDelta* rtt) const;
base::TimeDelta* rtt) const WARN_UNUSED_RESULT;

// Returns true if median downstream throughput is available and sets |kbps|
// to the median of downstream throughput (in kilobits per second)
// observations since |begin_timestamp|. Virtualized for testing. |kbps|
// should not be null.
virtual bool GetRecentMedianDownlinkThroughputKbps(
const base::TimeTicks& begin_timestamp,
int32_t* kbps) const;
int32_t* kbps) const WARN_UNUSED_RESULT;

// Adds |rtt_observer| to the list of round trip time observers. Must be
// called on the IO thread.
Expand Down Expand Up @@ -266,7 +268,6 @@ class NET_EXPORT_PRIVATE NetworkQualityEstimator

private:
FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, StoreObservations);
FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, TestKbpsRTTUpdates);
FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, TestAddObservation);
FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, ObtainOperatingParams);
FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, HalfLifeParam);
Expand Down Expand Up @@ -416,9 +417,6 @@ class NET_EXPORT_PRIVATE NetworkQualityEstimator
static_cast<size_t>(kMaximumObservationsBufferSize));
}

// Returns the number of observations in this buffer.
size_t Size() const { return observations_.size(); }

// Clears the observations stored in this buffer.
void Clear() { observations_.clear(); }

Expand All @@ -430,16 +428,14 @@ class NET_EXPORT_PRIVATE NetworkQualityEstimator
// than |begin_timestamp|. |result| must not be null.
// |disallowed_observation_sources| is the list of observation sources that
// should be excluded when computing the percentile.
bool GetPercentile(const base::TimeTicks& begin_timestamp,
ValueType* result,
int percentile,
const std::vector<ObservationSource>&
disallowed_observation_sources) const;
bool GetPercentile(
const base::TimeTicks& begin_timestamp,
ValueType* result,
int percentile,
const std::vector<ObservationSource>& disallowed_observation_sources)
const WARN_UNUSED_RESULT;

private:
FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, StoreObservations);
FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest,
ObtainOperatingParams);
FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, HalfLifeParam);

// Computes the weighted observations and stores them in
Expand Down Expand Up @@ -550,13 +546,16 @@ class NET_EXPORT_PRIVATE NetworkQualityEstimator
void AddDefaultEstimates();

// Returns an estimate of network quality at the specified |percentile|.
// |disallowed_observation_sources| is the list of observation sources that
// should be excluded when computing the percentile.
// Only the observations later than |begin_timestamp| are taken into account.
// |percentile| must be between 0 and 100 (both inclusive) with higher
// percentiles indicating less performant networks. For example, if
// |percentile| is 90, then the network is expected to be faster than the
// returned estimate with 0.9 probability. Similarly, network is expected to
// be slower than the returned estimate with 0.1 probability.
base::TimeDelta GetURLRequestRTTEstimateInternal(
base::TimeDelta GetRTTEstimateInternal(
const std::vector<ObservationSource>& disallowed_observation_sources,
const base::TimeTicks& begin_timestamp,
int percentile) const;
int32_t GetDownlinkThroughputKbpsEstimateInternal(
Expand Down
Loading

0 comments on commit e481a6c

Please sign in to comment.