| 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/nqe/network_quality_estimator.h" | 5 #include "net/nqe/network_quality_estimator.h" |
| 6 | 6 |
| 7 #include <float.h> | |
| 8 #include <algorithm> | 7 #include <algorithm> |
| 9 #include <cmath> | 8 #include <cmath> |
| 10 #include <limits> | 9 #include <limits> |
| 11 #include <utility> | 10 #include <utility> |
| 12 #include <vector> | 11 #include <vector> |
| 13 | 12 |
| 14 #include "base/logging.h" | 13 #include "base/logging.h" |
| 15 #include "base/metrics/histogram.h" | 14 #include "base/metrics/histogram.h" |
| 16 #include "base/metrics/histogram_base.h" | 15 #include "base/metrics/histogram_base.h" |
| 17 #include "base/strings/string_number_conversions.h" | 16 #include "base/strings/string_number_conversions.h" |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 209 } | 208 } |
| 210 | 209 |
| 211 private: | 210 private: |
| 212 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; | 211 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; |
| 213 | 212 |
| 214 base::WeakPtr<NetworkQualityEstimator> network_quality_estimator_; | 213 base::WeakPtr<NetworkQualityEstimator> network_quality_estimator_; |
| 215 | 214 |
| 216 DISALLOW_COPY_AND_ASSIGN(SocketWatcherFactory); | 215 DISALLOW_COPY_AND_ASSIGN(SocketWatcherFactory); |
| 217 }; | 216 }; |
| 218 | 217 |
| 219 const int32_t NetworkQualityEstimator::kInvalidThroughput = 0; | |
| 220 | |
| 221 NetworkQualityEstimator::NetworkQualityEstimator( | 218 NetworkQualityEstimator::NetworkQualityEstimator( |
| 222 std::unique_ptr<ExternalEstimateProvider> external_estimates_provider, | 219 std::unique_ptr<ExternalEstimateProvider> external_estimates_provider, |
| 223 const std::map<std::string, std::string>& variation_params) | 220 const std::map<std::string, std::string>& variation_params) |
| 224 : NetworkQualityEstimator(std::move(external_estimates_provider), | 221 : NetworkQualityEstimator(std::move(external_estimates_provider), |
| 225 variation_params, | 222 variation_params, |
| 226 false, | 223 false, |
| 227 false) {} | 224 false) {} |
| 228 | 225 |
| 229 NetworkQualityEstimator::NetworkQualityEstimator( | 226 NetworkQualityEstimator::NetworkQualityEstimator( |
| 230 std::unique_ptr<ExternalEstimateProvider> external_estimates_provider, | 227 std::unique_ptr<ExternalEstimateProvider> external_estimates_provider, |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 266 RecordExternalEstimateProviderMetrics( | 263 RecordExternalEstimateProviderMetrics( |
| 267 EXTERNAL_ESTIMATE_PROVIDER_STATUS_NOT_AVAILABLE); | 264 EXTERNAL_ESTIMATE_PROVIDER_STATUS_NOT_AVAILABLE); |
| 268 } | 265 } |
| 269 current_network_id_ = GetCurrentNetworkID(); | 266 current_network_id_ = GetCurrentNetworkID(); |
| 270 AddDefaultEstimates(); | 267 AddDefaultEstimates(); |
| 271 | 268 |
| 272 watcher_factory_.reset(new SocketWatcherFactory( | 269 watcher_factory_.reset(new SocketWatcherFactory( |
| 273 base::ThreadTaskRunnerHandle::Get(), weak_ptr_factory_.GetWeakPtr())); | 270 base::ThreadTaskRunnerHandle::Get(), weak_ptr_factory_.GetWeakPtr())); |
| 274 } | 271 } |
| 275 | 272 |
| 276 // static | |
| 277 const base::TimeDelta NetworkQualityEstimator::InvalidRTT() { | |
| 278 return base::TimeDelta::Max(); | |
| 279 } | |
| 280 | |
| 281 void NetworkQualityEstimator::ObtainOperatingParams( | 273 void NetworkQualityEstimator::ObtainOperatingParams( |
| 282 const std::map<std::string, std::string>& variation_params) { | 274 const std::map<std::string, std::string>& variation_params) { |
| 283 DCHECK(thread_checker_.CalledOnValidThread()); | 275 DCHECK(thread_checker_.CalledOnValidThread()); |
| 284 | 276 |
| 285 for (size_t i = 0; i <= NetworkChangeNotifier::CONNECTION_LAST; ++i) { | 277 for (size_t i = 0; i <= NetworkChangeNotifier::CONNECTION_LAST; ++i) { |
| 286 NetworkChangeNotifier::ConnectionType type = | 278 NetworkChangeNotifier::ConnectionType type = |
| 287 static_cast<NetworkChangeNotifier::ConnectionType>(i); | 279 static_cast<NetworkChangeNotifier::ConnectionType>(i); |
| 288 DCHECK_EQ(InvalidRTT(), default_observations_[i].rtt()); | 280 DCHECK_EQ(nqe::internal::InvalidRTT(), default_observations_[i].rtt()); |
| 289 DCHECK_EQ(kInvalidThroughput, | 281 DCHECK_EQ(nqe::internal::kInvalidThroughput, |
| 290 default_observations_[i].downstream_throughput_kbps()); | 282 default_observations_[i].downstream_throughput_kbps()); |
| 291 int32_t variations_value = kMinimumRTTVariationParameterMsec - 1; | 283 int32_t variations_value = kMinimumRTTVariationParameterMsec - 1; |
| 292 // Name of the parameter that holds the RTT value for this connection type. | 284 // Name of the parameter that holds the RTT value for this connection type. |
| 293 std::string rtt_parameter_name = | 285 std::string rtt_parameter_name = |
| 294 std::string(GetNameForConnectionType(type)) | 286 std::string(GetNameForConnectionType(type)) |
| 295 .append(kDefaultRTTMsecObservationSuffix); | 287 .append(kDefaultRTTMsecObservationSuffix); |
| 296 auto it = variation_params.find(rtt_parameter_name); | 288 auto it = variation_params.find(rtt_parameter_name); |
| 297 if (it != variation_params.end() && | 289 if (it != variation_params.end() && |
| 298 base::StringToInt(it->second, &variations_value) && | 290 base::StringToInt(it->second, &variations_value) && |
| 299 variations_value >= kMinimumRTTVariationParameterMsec) { | 291 variations_value >= kMinimumRTTVariationParameterMsec) { |
| 300 default_observations_[i] = | 292 default_observations_[i] = nqe::internal::NetworkQuality( |
| 301 NetworkQuality(base::TimeDelta::FromMilliseconds(variations_value), | 293 base::TimeDelta::FromMilliseconds(variations_value), |
| 302 default_observations_[i].downstream_throughput_kbps()); | 294 default_observations_[i].downstream_throughput_kbps()); |
| 303 } | 295 } |
| 304 | 296 |
| 305 variations_value = kMinimumThroughputVariationParameterKbps - 1; | 297 variations_value = kMinimumThroughputVariationParameterKbps - 1; |
| 306 // Name of the parameter that holds the Kbps value for this connection | 298 // Name of the parameter that holds the Kbps value for this connection |
| 307 // type. | 299 // type. |
| 308 std::string kbps_parameter_name = | 300 std::string kbps_parameter_name = |
| 309 std::string(GetNameForConnectionType(type)) | 301 std::string(GetNameForConnectionType(type)) |
| 310 .append(kDefaultKbpsObservationSuffix); | 302 .append(kDefaultKbpsObservationSuffix); |
| 311 it = variation_params.find(kbps_parameter_name); | 303 it = variation_params.find(kbps_parameter_name); |
| 312 if (it != variation_params.end() && | 304 if (it != variation_params.end() && |
| 313 base::StringToInt(it->second, &variations_value) && | 305 base::StringToInt(it->second, &variations_value) && |
| 314 variations_value >= kMinimumThroughputVariationParameterKbps) { | 306 variations_value >= kMinimumThroughputVariationParameterKbps) { |
| 315 default_observations_[i] = | 307 default_observations_[i] = nqe::internal::NetworkQuality( |
| 316 NetworkQuality(default_observations_[i].rtt(), variations_value); | 308 default_observations_[i].rtt(), variations_value); |
| 317 } | 309 } |
| 318 } | 310 } |
| 319 } | 311 } |
| 320 | 312 |
| 321 void NetworkQualityEstimator::ObtainEffectiveConnectionTypeModelParams( | 313 void NetworkQualityEstimator::ObtainEffectiveConnectionTypeModelParams( |
| 322 const std::map<std::string, std::string>& variation_params) { | 314 const std::map<std::string, std::string>& variation_params) { |
| 323 DCHECK(thread_checker_.CalledOnValidThread()); | 315 DCHECK(thread_checker_.CalledOnValidThread()); |
| 324 | 316 |
| 325 for (size_t i = 0; i < EFFECTIVE_CONNECTION_TYPE_LAST; ++i) { | 317 for (size_t i = 0; i < EFFECTIVE_CONNECTION_TYPE_LAST; ++i) { |
| 326 EffectiveConnectionType effective_connection_type = | 318 EffectiveConnectionType effective_connection_type = |
| 327 static_cast<EffectiveConnectionType>(i); | 319 static_cast<EffectiveConnectionType>(i); |
| 328 DCHECK_EQ(InvalidRTT(), connection_thresholds_[i].rtt()); | 320 DCHECK_EQ(nqe::internal::InvalidRTT(), connection_thresholds_[i].rtt()); |
| 329 DCHECK_EQ(kInvalidThroughput, | 321 DCHECK_EQ(nqe::internal::kInvalidThroughput, |
| 330 connection_thresholds_[i].downstream_throughput_kbps()); | 322 connection_thresholds_[i].downstream_throughput_kbps()); |
| 331 if (effective_connection_type == EFFECTIVE_CONNECTION_TYPE_UNKNOWN) | 323 if (effective_connection_type == EFFECTIVE_CONNECTION_TYPE_UNKNOWN) |
| 332 continue; | 324 continue; |
| 333 | 325 |
| 334 std::string connection_type_name = std::string( | 326 std::string connection_type_name = std::string( |
| 335 GetNameForEffectiveConnectionType(effective_connection_type)); | 327 GetNameForEffectiveConnectionType(effective_connection_type)); |
| 336 | 328 |
| 337 int32_t variations_value = kMinimumRTTVariationParameterMsec - 1; | 329 int32_t variations_value = kMinimumRTTVariationParameterMsec - 1; |
| 338 if (GetValueForVariationParam( | 330 if (GetValueForVariationParam( |
| 339 variation_params, connection_type_name + kThresholdURLRTTMsecSuffix, | 331 variation_params, connection_type_name + kThresholdURLRTTMsecSuffix, |
| 340 &variations_value) && | 332 &variations_value) && |
| 341 variations_value >= kMinimumRTTVariationParameterMsec) { | 333 variations_value >= kMinimumRTTVariationParameterMsec) { |
| 342 base::TimeDelta rtt(base::TimeDelta::FromMilliseconds(variations_value)); | 334 base::TimeDelta rtt(base::TimeDelta::FromMilliseconds(variations_value)); |
| 343 connection_thresholds_[i] = NetworkQuality( | 335 connection_thresholds_[i] = nqe::internal::NetworkQuality( |
| 344 rtt, connection_thresholds_[i].downstream_throughput_kbps()); | 336 rtt, connection_thresholds_[i].downstream_throughput_kbps()); |
| 345 | 337 |
| 346 // Verify that the RTT values are in decreasing order as the network | 338 // Verify that the RTT values are in decreasing order as the network |
| 347 // quality improves. | 339 // quality improves. |
| 348 DCHECK(i == 0 || connection_thresholds_[i - 1].rtt() == InvalidRTT() || | 340 DCHECK(i == 0 || |
| 341 connection_thresholds_[i - 1].rtt() == |
| 342 nqe::internal::InvalidRTT() || |
| 349 rtt <= connection_thresholds_[i - 1].rtt()); | 343 rtt <= connection_thresholds_[i - 1].rtt()); |
| 350 } | 344 } |
| 351 | 345 |
| 352 variations_value = kMinimumThroughputVariationParameterKbps - 1; | 346 variations_value = kMinimumThroughputVariationParameterKbps - 1; |
| 353 if (GetValueForVariationParam(variation_params, | 347 if (GetValueForVariationParam(variation_params, |
| 354 connection_type_name + kThresholdKbpsSuffix, | 348 connection_type_name + kThresholdKbpsSuffix, |
| 355 &variations_value) && | 349 &variations_value) && |
| 356 variations_value >= kMinimumThroughputVariationParameterKbps) { | 350 variations_value >= kMinimumThroughputVariationParameterKbps) { |
| 357 int32_t throughput_kbps = variations_value; | 351 int32_t throughput_kbps = variations_value; |
| 358 connection_thresholds_[i] = | 352 connection_thresholds_[i] = nqe::internal::NetworkQuality( |
| 359 NetworkQuality(connection_thresholds_[i].rtt(), throughput_kbps); | 353 connection_thresholds_[i].rtt(), throughput_kbps); |
| 360 | 354 |
| 361 // Verify that the throughput values are in increasing order as the | 355 // Verify that the throughput values are in increasing order as the |
| 362 // network quality improves. | 356 // network quality improves. |
| 363 DCHECK(i == 0 || | 357 DCHECK(i == 0 || |
| 364 connection_thresholds_[i - 1].downstream_throughput_kbps() == | 358 connection_thresholds_[i - 1].downstream_throughput_kbps() == |
| 365 kMinimumThroughputVariationParameterKbps || | 359 kMinimumThroughputVariationParameterKbps || |
| 366 throughput_kbps >= | 360 throughput_kbps >= |
| 367 connection_thresholds_[i - 1].downstream_throughput_kbps()); | 361 connection_thresholds_[i - 1].downstream_throughput_kbps()); |
| 368 } | 362 } |
| 369 } | 363 } |
| 370 } | 364 } |
| 371 | 365 |
| 372 void NetworkQualityEstimator::AddDefaultEstimates() { | 366 void NetworkQualityEstimator::AddDefaultEstimates() { |
| 373 DCHECK(thread_checker_.CalledOnValidThread()); | 367 DCHECK(thread_checker_.CalledOnValidThread()); |
| 374 if (default_observations_[current_network_id_.type].rtt() != InvalidRTT()) { | 368 if (default_observations_[current_network_id_.type].rtt() != |
| 369 nqe::internal::InvalidRTT()) { |
| 375 RttObservation rtt_observation( | 370 RttObservation rtt_observation( |
| 376 default_observations_[current_network_id_.type].rtt(), | 371 default_observations_[current_network_id_.type].rtt(), |
| 377 base::TimeTicks::Now(), DEFAULT_FROM_PLATFORM); | 372 base::TimeTicks::Now(), |
| 373 NETWORK_QUALITY_OBSERVATION_SOURCE_DEFAULT_FROM_PLATFORM); |
| 378 rtt_observations_.AddObservation(rtt_observation); | 374 rtt_observations_.AddObservation(rtt_observation); |
| 379 NotifyObserversOfRTT(rtt_observation); | 375 NotifyObserversOfRTT(rtt_observation); |
| 380 } | 376 } |
| 381 if (default_observations_[current_network_id_.type] | 377 if (default_observations_[current_network_id_.type] |
| 382 .downstream_throughput_kbps() != kInvalidThroughput) { | 378 .downstream_throughput_kbps() != nqe::internal::kInvalidThroughput) { |
| 383 ThroughputObservation throughput_observation( | 379 ThroughputObservation throughput_observation( |
| 384 default_observations_[current_network_id_.type] | 380 default_observations_[current_network_id_.type] |
| 385 .downstream_throughput_kbps(), | 381 .downstream_throughput_kbps(), |
| 386 base::TimeTicks::Now(), DEFAULT_FROM_PLATFORM); | 382 base::TimeTicks::Now(), |
| 383 NETWORK_QUALITY_OBSERVATION_SOURCE_DEFAULT_FROM_PLATFORM); |
| 387 downstream_throughput_kbps_observations_.AddObservation( | 384 downstream_throughput_kbps_observations_.AddObservation( |
| 388 throughput_observation); | 385 throughput_observation); |
| 389 NotifyObserversOfThroughput(throughput_observation); | 386 NotifyObserversOfThroughput(throughput_observation); |
| 390 } | 387 } |
| 391 } | 388 } |
| 392 | 389 |
| 393 NetworkQualityEstimator::~NetworkQualityEstimator() { | 390 NetworkQualityEstimator::~NetworkQualityEstimator() { |
| 394 DCHECK(thread_checker_.CalledOnValidThread()); | 391 DCHECK(thread_checker_.CalledOnValidThread()); |
| 395 NetworkChangeNotifier::RemoveConnectionTypeObserver(this); | 392 NetworkChangeNotifier::RemoveConnectionTypeObserver(this); |
| 396 } | 393 } |
| 397 | 394 |
| 398 void NetworkQualityEstimator::NotifyHeadersReceived(const URLRequest& request) { | 395 void NetworkQualityEstimator::NotifyHeadersReceived(const URLRequest& request) { |
| 399 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("net"), | 396 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("net"), |
| 400 "NetworkQualityEstimator::NotifyHeadersReceived"); | 397 "NetworkQualityEstimator::NotifyHeadersReceived"); |
| 401 DCHECK(thread_checker_.CalledOnValidThread()); | 398 DCHECK(thread_checker_.CalledOnValidThread()); |
| 402 | 399 |
| 403 if (!RequestProvidesUsefulObservations(request)) | 400 if (!RequestProvidesUsefulObservations(request)) |
| 404 return; | 401 return; |
| 405 | 402 |
| 406 // Update |estimated_median_network_quality_| if this is a main frame request. | 403 // Update |estimated_median_network_quality_| if this is a main frame request. |
| 407 if (request.load_flags() & LOAD_MAIN_FRAME) { | 404 if (request.load_flags() & LOAD_MAIN_FRAME) { |
| 408 base::TimeDelta rtt; | 405 base::TimeDelta rtt; |
| 409 if (!GetURLRequestRTTEstimate(&rtt)) | 406 if (!GetURLRequestRTTEstimate(&rtt)) |
| 410 rtt = InvalidRTT(); | 407 rtt = nqe::internal::InvalidRTT(); |
| 411 | 408 |
| 412 int32_t downstream_throughput_kbps; | 409 int32_t downstream_throughput_kbps; |
| 413 if (!GetDownlinkThroughputKbpsEstimate(&downstream_throughput_kbps)) | 410 if (!GetDownlinkThroughputKbpsEstimate(&downstream_throughput_kbps)) |
| 414 downstream_throughput_kbps = kInvalidThroughput; | 411 downstream_throughput_kbps = nqe::internal::kInvalidThroughput; |
| 415 | 412 |
| 416 estimated_median_network_quality_ = | 413 estimated_median_network_quality_ = |
| 417 NetworkQuality(rtt, downstream_throughput_kbps); | 414 nqe::internal::NetworkQuality(rtt, downstream_throughput_kbps); |
| 418 } | 415 } |
| 419 | 416 |
| 420 base::TimeTicks now = base::TimeTicks::Now(); | 417 base::TimeTicks now = base::TimeTicks::Now(); |
| 421 LoadTimingInfo load_timing_info; | 418 LoadTimingInfo load_timing_info; |
| 422 request.GetLoadTimingInfo(&load_timing_info); | 419 request.GetLoadTimingInfo(&load_timing_info); |
| 423 | 420 |
| 424 // If the load timing info is unavailable, it probably means that the request | 421 // If the load timing info is unavailable, it probably means that the request |
| 425 // did not go over the network. | 422 // did not go over the network. |
| 426 if (load_timing_info.send_start.is_null() || | 423 if (load_timing_info.send_start.is_null() || |
| 427 load_timing_info.receive_headers_end.is_null()) { | 424 load_timing_info.receive_headers_end.is_null()) { |
| 428 return; | 425 return; |
| 429 } | 426 } |
| 430 | 427 |
| 431 // Time when the resource was requested. | 428 // Time when the resource was requested. |
| 432 base::TimeTicks request_start_time = load_timing_info.send_start; | 429 base::TimeTicks request_start_time = load_timing_info.send_start; |
| 433 | 430 |
| 434 // Time when the headers were received. | 431 // Time when the headers were received. |
| 435 base::TimeTicks headers_received_time = load_timing_info.receive_headers_end; | 432 base::TimeTicks headers_received_time = load_timing_info.receive_headers_end; |
| 436 | 433 |
| 437 // Duration between when the resource was requested and when response | 434 // Duration between when the resource was requested and when response |
| 438 // headers were received. | 435 // headers were received. |
| 439 base::TimeDelta observed_rtt = headers_received_time - request_start_time; | 436 base::TimeDelta observed_rtt = headers_received_time - request_start_time; |
| 440 DCHECK_GE(observed_rtt, base::TimeDelta()); | 437 DCHECK_GE(observed_rtt, base::TimeDelta()); |
| 441 if (observed_rtt < peak_network_quality_.rtt()) { | 438 if (observed_rtt < peak_network_quality_.rtt()) { |
| 442 peak_network_quality_ = NetworkQuality( | 439 peak_network_quality_ = nqe::internal::NetworkQuality( |
| 443 observed_rtt, peak_network_quality_.downstream_throughput_kbps()); | 440 observed_rtt, peak_network_quality_.downstream_throughput_kbps()); |
| 444 } | 441 } |
| 445 | 442 |
| 446 RttObservation rtt_observation(observed_rtt, now, URL_REQUEST); | 443 RttObservation rtt_observation( |
| 444 observed_rtt, now, NETWORK_QUALITY_OBSERVATION_SOURCE_URL_REQUEST); |
| 447 rtt_observations_.AddObservation(rtt_observation); | 445 rtt_observations_.AddObservation(rtt_observation); |
| 448 NotifyObserversOfRTT(rtt_observation); | 446 NotifyObserversOfRTT(rtt_observation); |
| 449 | 447 |
| 450 // Compare the RTT observation with the estimated value and record it. | 448 // Compare the RTT observation with the estimated value and record it. |
| 451 if (estimated_median_network_quality_.rtt() != InvalidRTT()) { | 449 if (estimated_median_network_quality_.rtt() != nqe::internal::InvalidRTT()) { |
| 452 RecordRTTUMA(estimated_median_network_quality_.rtt().InMilliseconds(), | 450 RecordRTTUMA(estimated_median_network_quality_.rtt().InMilliseconds(), |
| 453 observed_rtt.InMilliseconds()); | 451 observed_rtt.InMilliseconds()); |
| 454 } | 452 } |
| 455 } | 453 } |
| 456 | 454 |
| 457 void NetworkQualityEstimator::NotifyRequestCompleted( | 455 void NetworkQualityEstimator::NotifyRequestCompleted( |
| 458 const URLRequest& request) { | 456 const URLRequest& request) { |
| 459 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("net"), | 457 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("net"), |
| 460 "NetworkQualityEstimator::NotifyRequestCompleted"); | 458 "NetworkQualityEstimator::NotifyRequestCompleted"); |
| 461 DCHECK(thread_checker_.CalledOnValidThread()); | 459 DCHECK(thread_checker_.CalledOnValidThread()); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 504 | 502 |
| 505 // Round up |downstream_kbps_as_integer|. If the |downstream_kbps_as_integer| | 503 // Round up |downstream_kbps_as_integer|. If the |downstream_kbps_as_integer| |
| 506 // is less than 1, it is set to 1 to differentiate from case when there is no | 504 // is less than 1, it is set to 1 to differentiate from case when there is no |
| 507 // connection. | 505 // connection. |
| 508 if (downstream_kbps - downstream_kbps_as_integer > 0) | 506 if (downstream_kbps - downstream_kbps_as_integer > 0) |
| 509 downstream_kbps_as_integer++; | 507 downstream_kbps_as_integer++; |
| 510 | 508 |
| 511 DCHECK_GT(downstream_kbps_as_integer, 0.0); | 509 DCHECK_GT(downstream_kbps_as_integer, 0.0); |
| 512 if (downstream_kbps_as_integer > | 510 if (downstream_kbps_as_integer > |
| 513 peak_network_quality_.downstream_throughput_kbps()) | 511 peak_network_quality_.downstream_throughput_kbps()) |
| 514 peak_network_quality_ = | 512 peak_network_quality_ = nqe::internal::NetworkQuality( |
| 515 NetworkQuality(peak_network_quality_.rtt(), downstream_kbps_as_integer); | 513 peak_network_quality_.rtt(), downstream_kbps_as_integer); |
| 516 | 514 |
| 517 ThroughputObservation throughput_observation(downstream_kbps_as_integer, now, | 515 ThroughputObservation throughput_observation( |
| 518 URL_REQUEST); | 516 downstream_kbps_as_integer, now, |
| 517 NETWORK_QUALITY_OBSERVATION_SOURCE_URL_REQUEST); |
| 519 downstream_throughput_kbps_observations_.AddObservation( | 518 downstream_throughput_kbps_observations_.AddObservation( |
| 520 throughput_observation); | 519 throughput_observation); |
| 521 NotifyObserversOfThroughput(throughput_observation); | 520 NotifyObserversOfThroughput(throughput_observation); |
| 522 } | 521 } |
| 523 | 522 |
| 524 void NetworkQualityEstimator::AddRTTObserver(RTTObserver* rtt_observer) { | 523 void NetworkQualityEstimator::AddRTTObserver(RTTObserver* rtt_observer) { |
| 525 DCHECK(thread_checker_.CalledOnValidThread()); | 524 DCHECK(thread_checker_.CalledOnValidThread()); |
| 526 rtt_observer_list_.AddObserver(rtt_observer); | 525 rtt_observer_list_.AddObserver(rtt_observer); |
| 527 } | 526 } |
| 528 | 527 |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 599 | 598 |
| 600 void NetworkQualityEstimator::RecordExternalEstimateProviderMetrics( | 599 void NetworkQualityEstimator::RecordExternalEstimateProviderMetrics( |
| 601 NQEExternalEstimateProviderStatus status) const { | 600 NQEExternalEstimateProviderStatus status) const { |
| 602 UMA_HISTOGRAM_ENUMERATION("NQE.ExternalEstimateProviderStatus", status, | 601 UMA_HISTOGRAM_ENUMERATION("NQE.ExternalEstimateProviderStatus", status, |
| 603 EXTERNAL_ESTIMATE_PROVIDER_STATUS_BOUNDARY); | 602 EXTERNAL_ESTIMATE_PROVIDER_STATUS_BOUNDARY); |
| 604 } | 603 } |
| 605 | 604 |
| 606 void NetworkQualityEstimator::OnConnectionTypeChanged( | 605 void NetworkQualityEstimator::OnConnectionTypeChanged( |
| 607 NetworkChangeNotifier::ConnectionType type) { | 606 NetworkChangeNotifier::ConnectionType type) { |
| 608 DCHECK(thread_checker_.CalledOnValidThread()); | 607 DCHECK(thread_checker_.CalledOnValidThread()); |
| 609 if (peak_network_quality_.rtt() != InvalidRTT()) { | 608 if (peak_network_quality_.rtt() != nqe::internal::InvalidRTT()) { |
| 610 base::HistogramBase* rtt_histogram = | 609 base::HistogramBase* rtt_histogram = |
| 611 GetHistogram("FastestRTT.", current_network_id_.type, 10 * 1000); | 610 GetHistogram("FastestRTT.", current_network_id_.type, 10 * 1000); |
| 612 rtt_histogram->Add(peak_network_quality_.rtt().InMilliseconds()); | 611 rtt_histogram->Add(peak_network_quality_.rtt().InMilliseconds()); |
| 613 } | 612 } |
| 614 | 613 |
| 615 if (peak_network_quality_.downstream_throughput_kbps() != | 614 if (peak_network_quality_.downstream_throughput_kbps() != |
| 616 kInvalidThroughput) { | 615 nqe::internal::kInvalidThroughput) { |
| 617 base::HistogramBase* downstream_throughput_histogram = | 616 base::HistogramBase* downstream_throughput_histogram = |
| 618 GetHistogram("PeakKbps.", current_network_id_.type, 1000 * 1000); | 617 GetHistogram("PeakKbps.", current_network_id_.type, 1000 * 1000); |
| 619 downstream_throughput_histogram->Add( | 618 downstream_throughput_histogram->Add( |
| 620 peak_network_quality_.downstream_throughput_kbps()); | 619 peak_network_quality_.downstream_throughput_kbps()); |
| 621 } | 620 } |
| 622 | 621 |
| 623 base::TimeDelta rtt; | 622 base::TimeDelta rtt; |
| 624 if (GetURLRequestRTTEstimate(&rtt)) { | 623 if (GetURLRequestRTTEstimate(&rtt)) { |
| 625 // Add the 50th percentile value. | 624 // Add the 50th percentile value. |
| 626 base::HistogramBase* rtt_percentile = | 625 base::HistogramBase* rtt_percentile = |
| 627 GetHistogram("RTT.Percentile50.", current_network_id_.type, 10 * 1000); | 626 GetHistogram("RTT.Percentile50.", current_network_id_.type, 10 * 1000); |
| 628 rtt_percentile->Add(rtt.InMilliseconds()); | 627 rtt_percentile->Add(rtt.InMilliseconds()); |
| 629 | 628 |
| 630 // Add the remaining percentile values. | 629 // Add the remaining percentile values. |
| 631 static const int kPercentiles[] = {0, 10, 90, 100}; | 630 static const int kPercentiles[] = {0, 10, 90, 100}; |
| 632 std::vector<ObservationSource> disallowed_observation_sources; | 631 std::vector<NetworkQualityObservationSource> disallowed_observation_sources; |
| 633 disallowed_observation_sources.push_back(TCP); | 632 disallowed_observation_sources.push_back( |
| 634 disallowed_observation_sources.push_back(QUIC); | 633 NETWORK_QUALITY_OBSERVATION_SOURCE_TCP); |
| 634 disallowed_observation_sources.push_back( |
| 635 NETWORK_QUALITY_OBSERVATION_SOURCE_QUIC); |
| 635 for (size_t i = 0; i < arraysize(kPercentiles); ++i) { | 636 for (size_t i = 0; i < arraysize(kPercentiles); ++i) { |
| 636 rtt = GetRTTEstimateInternal(disallowed_observation_sources, | 637 rtt = GetRTTEstimateInternal(disallowed_observation_sources, |
| 637 base::TimeTicks(), kPercentiles[i]); | 638 base::TimeTicks(), kPercentiles[i]); |
| 638 | 639 |
| 639 rtt_percentile = GetHistogram( | 640 rtt_percentile = GetHistogram( |
| 640 "RTT.Percentile" + base::IntToString(kPercentiles[i]) + ".", | 641 "RTT.Percentile" + base::IntToString(kPercentiles[i]) + ".", |
| 641 current_network_id_.type, 10 * 1000); // 10 seconds | 642 current_network_id_.type, 10 * 1000); // 10 seconds |
| 642 rtt_percentile->Add(rtt.InMilliseconds()); | 643 rtt_percentile->Add(rtt.InMilliseconds()); |
| 643 } | 644 } |
| 644 } | 645 } |
| 645 | 646 |
| 646 // Write the estimates of the previous network to the cache. | 647 // Write the estimates of the previous network to the cache. |
| 647 CacheNetworkQualityEstimate(); | 648 CacheNetworkQualityEstimate(); |
| 648 | 649 |
| 649 // Clear the local state. | 650 // Clear the local state. |
| 650 last_connection_change_ = base::TimeTicks::Now(); | 651 last_connection_change_ = base::TimeTicks::Now(); |
| 651 peak_network_quality_ = NetworkQuality(); | 652 peak_network_quality_ = nqe::internal::NetworkQuality(); |
| 652 downstream_throughput_kbps_observations_.Clear(); | 653 downstream_throughput_kbps_observations_.Clear(); |
| 653 rtt_observations_.Clear(); | 654 rtt_observations_.Clear(); |
| 654 current_network_id_ = GetCurrentNetworkID(); | 655 current_network_id_ = GetCurrentNetworkID(); |
| 655 | 656 |
| 656 QueryExternalEstimateProvider(); | 657 QueryExternalEstimateProvider(); |
| 657 | 658 |
| 658 // Read any cached estimates for the new network. If cached estimates are | 659 // Read any cached estimates for the new network. If cached estimates are |
| 659 // unavailable, add the default estimates. | 660 // unavailable, add the default estimates. |
| 660 if (!ReadCachedNetworkQualityEstimate()) | 661 if (!ReadCachedNetworkQualityEstimate()) |
| 661 AddDefaultEstimates(); | 662 AddDefaultEstimates(); |
| 662 estimated_median_network_quality_ = NetworkQuality(); | 663 estimated_median_network_quality_ = nqe::internal::NetworkQuality(); |
| 663 } | 664 } |
| 664 | 665 |
| 665 NetworkQualityEstimator::EffectiveConnectionType | 666 NetworkQualityEstimator::EffectiveConnectionType |
| 666 NetworkQualityEstimator::GetEffectiveConnectionType() const { | 667 NetworkQualityEstimator::GetEffectiveConnectionType() const { |
| 667 DCHECK(thread_checker_.CalledOnValidThread()); | 668 DCHECK(thread_checker_.CalledOnValidThread()); |
| 668 | 669 |
| 669 base::TimeDelta url_request_rtt = InvalidRTT(); | 670 base::TimeDelta url_request_rtt = nqe::internal::InvalidRTT(); |
| 670 if (!GetURLRequestRTTEstimate(&url_request_rtt)) | 671 if (!GetURLRequestRTTEstimate(&url_request_rtt)) |
| 671 url_request_rtt = InvalidRTT(); | 672 url_request_rtt = nqe::internal::InvalidRTT(); |
| 672 | 673 |
| 673 int32_t kbps = kInvalidThroughput; | 674 int32_t kbps = nqe::internal::kInvalidThroughput; |
| 674 if (!GetDownlinkThroughputKbpsEstimate(&kbps)) | 675 if (!GetDownlinkThroughputKbpsEstimate(&kbps)) |
| 675 kbps = kInvalidThroughput; | 676 kbps = nqe::internal::kInvalidThroughput; |
| 676 | 677 |
| 677 if (url_request_rtt == InvalidRTT() && kbps == kInvalidThroughput) { | 678 if (url_request_rtt == nqe::internal::InvalidRTT() && |
| 679 kbps == nqe::internal::kInvalidThroughput) { |
| 678 // Quality of the current network is unknown. | 680 // Quality of the current network is unknown. |
| 679 return EFFECTIVE_CONNECTION_TYPE_UNKNOWN; | 681 return EFFECTIVE_CONNECTION_TYPE_UNKNOWN; |
| 680 } | 682 } |
| 681 | 683 |
| 682 // Search from the slowest connection type to the fastest to find the | 684 // Search from the slowest connection type to the fastest to find the |
| 683 // EffectiveConnectionType that best matches the current connection's | 685 // EffectiveConnectionType that best matches the current connection's |
| 684 // performance. The match is done by comparing RTT and throughput. | 686 // performance. The match is done by comparing RTT and throughput. |
| 685 for (size_t i = 0; i < EFFECTIVE_CONNECTION_TYPE_LAST; ++i) { | 687 for (size_t i = 0; i < EFFECTIVE_CONNECTION_TYPE_LAST; ++i) { |
| 686 EffectiveConnectionType type = static_cast<EffectiveConnectionType>(i); | 688 EffectiveConnectionType type = static_cast<EffectiveConnectionType>(i); |
| 687 if (i == EFFECTIVE_CONNECTION_TYPE_UNKNOWN) | 689 if (i == EFFECTIVE_CONNECTION_TYPE_UNKNOWN) |
| 688 continue; | 690 continue; |
| 689 bool estimated_rtt_is_higher_than_threshold = | 691 bool estimated_rtt_is_higher_than_threshold = |
| 690 url_request_rtt != InvalidRTT() && | 692 url_request_rtt != nqe::internal::InvalidRTT() && |
| 691 connection_thresholds_[i].rtt() != InvalidRTT() && | 693 connection_thresholds_[i].rtt() != nqe::internal::InvalidRTT() && |
| 692 url_request_rtt >= connection_thresholds_[i].rtt(); | 694 url_request_rtt >= connection_thresholds_[i].rtt(); |
| 693 bool estimated_throughput_is_lower_than_threshold = | 695 bool estimated_throughput_is_lower_than_threshold = |
| 694 kbps != kInvalidThroughput && | 696 kbps != nqe::internal::kInvalidThroughput && |
| 695 connection_thresholds_[i].downstream_throughput_kbps() != | 697 connection_thresholds_[i].downstream_throughput_kbps() != |
| 696 kInvalidThroughput && | 698 nqe::internal::kInvalidThroughput && |
| 697 kbps <= connection_thresholds_[i].downstream_throughput_kbps(); | 699 kbps <= connection_thresholds_[i].downstream_throughput_kbps(); |
| 698 // Return |type| as the effective connection type if the current network's | 700 // Return |type| as the effective connection type if the current network's |
| 699 // RTT is worse than the threshold RTT for |type|, or if the current | 701 // RTT is worse than the threshold RTT for |type|, or if the current |
| 700 // network's throughput is lower than the threshold throughput for |type|. | 702 // network's throughput is lower than the threshold throughput for |type|. |
| 701 if (estimated_rtt_is_higher_than_threshold || | 703 if (estimated_rtt_is_higher_than_threshold || |
| 702 estimated_throughput_is_lower_than_threshold) { | 704 estimated_throughput_is_lower_than_threshold) { |
| 703 return type; | 705 return type; |
| 704 } | 706 } |
| 705 } | 707 } |
| 706 // Return the fastest connection type. | 708 // Return the fastest connection type. |
| 707 return static_cast<EffectiveConnectionType>(EFFECTIVE_CONNECTION_TYPE_LAST - | 709 return static_cast<EffectiveConnectionType>(EFFECTIVE_CONNECTION_TYPE_LAST - |
| 708 1); | 710 1); |
| 709 } | 711 } |
| 710 | 712 |
| 711 bool NetworkQualityEstimator::GetURLRequestRTTEstimate( | 713 bool NetworkQualityEstimator::GetURLRequestRTTEstimate( |
| 712 base::TimeDelta* rtt) const { | 714 base::TimeDelta* rtt) const { |
| 713 DCHECK(thread_checker_.CalledOnValidThread()); | 715 DCHECK(thread_checker_.CalledOnValidThread()); |
| 714 std::vector<ObservationSource> disallowed_observation_sources; | 716 std::vector<NetworkQualityObservationSource> disallowed_observation_sources; |
| 715 disallowed_observation_sources.push_back(TCP); | 717 disallowed_observation_sources.push_back( |
| 716 disallowed_observation_sources.push_back(QUIC); | 718 NETWORK_QUALITY_OBSERVATION_SOURCE_TCP); |
| 719 disallowed_observation_sources.push_back( |
| 720 NETWORK_QUALITY_OBSERVATION_SOURCE_QUIC); |
| 717 *rtt = GetRTTEstimateInternal(disallowed_observation_sources, | 721 *rtt = GetRTTEstimateInternal(disallowed_observation_sources, |
| 718 base::TimeTicks(), 50); | 722 base::TimeTicks(), 50); |
| 719 return (*rtt != InvalidRTT()); | 723 return (*rtt != nqe::internal::InvalidRTT()); |
| 720 } | 724 } |
| 721 | 725 |
| 722 bool NetworkQualityEstimator::GetDownlinkThroughputKbpsEstimate( | 726 bool NetworkQualityEstimator::GetDownlinkThroughputKbpsEstimate( |
| 723 int32_t* kbps) const { | 727 int32_t* kbps) const { |
| 724 DCHECK(thread_checker_.CalledOnValidThread()); | 728 DCHECK(thread_checker_.CalledOnValidThread()); |
| 725 *kbps = GetDownlinkThroughputKbpsEstimateInternal(base::TimeTicks(), 50); | 729 *kbps = GetDownlinkThroughputKbpsEstimateInternal(base::TimeTicks(), 50); |
| 726 return (*kbps != kInvalidThroughput); | 730 return (*kbps != nqe::internal::kInvalidThroughput); |
| 727 } | 731 } |
| 728 | 732 |
| 729 bool NetworkQualityEstimator::GetRecentURLRequestRTTMedian( | 733 bool NetworkQualityEstimator::GetRecentURLRequestRTTMedian( |
| 730 const base::TimeTicks& begin_timestamp, | 734 const base::TimeTicks& begin_timestamp, |
| 731 base::TimeDelta* rtt) const { | 735 base::TimeDelta* rtt) const { |
| 732 DCHECK(thread_checker_.CalledOnValidThread()); | 736 DCHECK(thread_checker_.CalledOnValidThread()); |
| 733 std::vector<ObservationSource> disallowed_observation_sources; | 737 std::vector<NetworkQualityObservationSource> disallowed_observation_sources; |
| 734 disallowed_observation_sources.push_back(TCP); | 738 disallowed_observation_sources.push_back( |
| 735 disallowed_observation_sources.push_back(QUIC); | 739 NETWORK_QUALITY_OBSERVATION_SOURCE_TCP); |
| 740 disallowed_observation_sources.push_back( |
| 741 NETWORK_QUALITY_OBSERVATION_SOURCE_QUIC); |
| 736 *rtt = GetRTTEstimateInternal(disallowed_observation_sources, begin_timestamp, | 742 *rtt = GetRTTEstimateInternal(disallowed_observation_sources, begin_timestamp, |
| 737 50); | 743 50); |
| 738 return (*rtt != InvalidRTT()); | 744 return (*rtt != nqe::internal::InvalidRTT()); |
| 739 } | 745 } |
| 740 | 746 |
| 741 bool NetworkQualityEstimator::GetRecentMedianDownlinkThroughputKbps( | 747 bool NetworkQualityEstimator::GetRecentMedianDownlinkThroughputKbps( |
| 742 const base::TimeTicks& begin_timestamp, | 748 const base::TimeTicks& begin_timestamp, |
| 743 int32_t* kbps) const { | 749 int32_t* kbps) const { |
| 744 DCHECK(thread_checker_.CalledOnValidThread()); | 750 DCHECK(thread_checker_.CalledOnValidThread()); |
| 745 *kbps = GetDownlinkThroughputKbpsEstimateInternal(begin_timestamp, 50); | 751 *kbps = GetDownlinkThroughputKbpsEstimateInternal(begin_timestamp, 50); |
| 746 return (*kbps != kInvalidThroughput); | 752 return (*kbps != nqe::internal::kInvalidThroughput); |
| 747 } | 753 } |
| 748 | 754 |
| 749 template <typename ValueType> | |
| 750 NetworkQualityEstimator::ObservationBuffer<ValueType>::ObservationBuffer( | |
| 751 double weight_multiplier_per_second) | |
| 752 : weight_multiplier_per_second_(weight_multiplier_per_second) { | |
| 753 static_assert(kMaximumObservationsBufferSize > 0U, | |
| 754 "Minimum size of observation buffer must be > 0"); | |
| 755 DCHECK_GE(weight_multiplier_per_second_, 0.0); | |
| 756 DCHECK_LE(weight_multiplier_per_second_, 1.0); | |
| 757 } | |
| 758 | |
| 759 template <typename ValueType> | |
| 760 NetworkQualityEstimator::ObservationBuffer<ValueType>::~ObservationBuffer() {} | |
| 761 | |
| 762 base::TimeDelta NetworkQualityEstimator::GetRTTEstimateInternal( | 755 base::TimeDelta NetworkQualityEstimator::GetRTTEstimateInternal( |
| 763 const std::vector<ObservationSource>& disallowed_observation_sources, | 756 const std::vector<NetworkQualityObservationSource>& |
| 757 disallowed_observation_sources, |
| 764 const base::TimeTicks& begin_timestamp, | 758 const base::TimeTicks& begin_timestamp, |
| 765 int percentile) const { | 759 int percentile) const { |
| 766 DCHECK(thread_checker_.CalledOnValidThread()); | 760 DCHECK(thread_checker_.CalledOnValidThread()); |
| 767 | 761 |
| 768 // RTT observations are sorted by duration from shortest to longest, thus | 762 // RTT observations are sorted by duration from shortest to longest, thus |
| 769 // a higher percentile RTT will have a longer RTT than a lower percentile. | 763 // a higher percentile RTT will have a longer RTT than a lower percentile. |
| 770 base::TimeDelta rtt = InvalidRTT(); | 764 base::TimeDelta rtt = nqe::internal::InvalidRTT(); |
| 771 if (!rtt_observations_.GetPercentile(begin_timestamp, &rtt, percentile, | 765 if (!rtt_observations_.GetPercentile(begin_timestamp, &rtt, percentile, |
| 772 disallowed_observation_sources)) { | 766 disallowed_observation_sources)) { |
| 773 return InvalidRTT(); | 767 return nqe::internal::InvalidRTT(); |
| 774 } | 768 } |
| 775 return rtt; | 769 return rtt; |
| 776 } | 770 } |
| 777 | 771 |
| 778 int32_t NetworkQualityEstimator::GetDownlinkThroughputKbpsEstimateInternal( | 772 int32_t NetworkQualityEstimator::GetDownlinkThroughputKbpsEstimateInternal( |
| 779 const base::TimeTicks& begin_timestamp, | 773 const base::TimeTicks& begin_timestamp, |
| 780 int percentile) const { | 774 int percentile) const { |
| 781 DCHECK(thread_checker_.CalledOnValidThread()); | 775 DCHECK(thread_checker_.CalledOnValidThread()); |
| 782 | 776 |
| 783 // Throughput observations are sorted by kbps from slowest to fastest, | 777 // Throughput observations are sorted by kbps from slowest to fastest, |
| 784 // thus a higher percentile throughput will be faster than a lower one. | 778 // thus a higher percentile throughput will be faster than a lower one. |
| 785 int32_t kbps = kInvalidThroughput; | 779 int32_t kbps = nqe::internal::kInvalidThroughput; |
| 786 if (!downstream_throughput_kbps_observations_.GetPercentile( | 780 if (!downstream_throughput_kbps_observations_.GetPercentile( |
| 787 begin_timestamp, &kbps, 100 - percentile, | 781 begin_timestamp, &kbps, 100 - percentile, |
| 788 std::vector<ObservationSource>())) { | 782 std::vector<NetworkQualityObservationSource>())) { |
| 789 return kInvalidThroughput; | 783 return nqe::internal::kInvalidThroughput; |
| 790 } | 784 } |
| 791 return kbps; | 785 return kbps; |
| 792 } | 786 } |
| 793 | 787 |
| 794 template <typename ValueType> | |
| 795 void NetworkQualityEstimator::ObservationBuffer<ValueType>:: | |
| 796 ComputeWeightedObservations( | |
| 797 const base::TimeTicks& begin_timestamp, | |
| 798 std::vector<WeightedObservation<ValueType>>& weighted_observations, | |
| 799 double* total_weight, | |
| 800 const std::vector<ObservationSource>& disallowed_observation_sources) | |
| 801 const { | |
| 802 weighted_observations.clear(); | |
| 803 double total_weight_observations = 0.0; | |
| 804 base::TimeTicks now = base::TimeTicks::Now(); | |
| 805 | |
| 806 for (const auto& observation : observations_) { | |
| 807 if (observation.timestamp < begin_timestamp) | |
| 808 continue; | |
| 809 bool disallowed = false; | |
| 810 for (const auto& disallowed_source : disallowed_observation_sources) { | |
| 811 if (disallowed_source == observation.source) | |
| 812 disallowed = true; | |
| 813 } | |
| 814 if (disallowed) | |
| 815 continue; | |
| 816 base::TimeDelta time_since_sample_taken = now - observation.timestamp; | |
| 817 double weight = | |
| 818 pow(weight_multiplier_per_second_, time_since_sample_taken.InSeconds()); | |
| 819 weight = std::max(DBL_MIN, std::min(1.0, weight)); | |
| 820 | |
| 821 weighted_observations.push_back( | |
| 822 WeightedObservation<ValueType>(observation.value, weight)); | |
| 823 total_weight_observations += weight; | |
| 824 } | |
| 825 | |
| 826 // Sort the samples by value in ascending order. | |
| 827 std::sort(weighted_observations.begin(), weighted_observations.end()); | |
| 828 *total_weight = total_weight_observations; | |
| 829 } | |
| 830 | |
| 831 template <typename ValueType> | |
| 832 bool NetworkQualityEstimator::ObservationBuffer<ValueType>::GetPercentile( | |
| 833 const base::TimeTicks& begin_timestamp, | |
| 834 ValueType* result, | |
| 835 int percentile, | |
| 836 const std::vector<ObservationSource>& disallowed_observation_sources) | |
| 837 const { | |
| 838 DCHECK(result); | |
| 839 DCHECK_GE(percentile, 0); | |
| 840 DCHECK_LE(percentile, 100); | |
| 841 | |
| 842 // Stores WeightedObservation in increasing order of value. | |
| 843 std::vector<WeightedObservation<ValueType>> weighted_observations; | |
| 844 | |
| 845 // Total weight of all observations in |weighted_observations|. | |
| 846 double total_weight = 0.0; | |
| 847 | |
| 848 ComputeWeightedObservations(begin_timestamp, weighted_observations, | |
| 849 &total_weight, disallowed_observation_sources); | |
| 850 if (weighted_observations.empty()) | |
| 851 return false; | |
| 852 | |
| 853 DCHECK(!weighted_observations.empty()); | |
| 854 DCHECK_GT(total_weight, 0.0); | |
| 855 | |
| 856 // weighted_observations may have a smaller size than observations_ since the | |
| 857 // former contains only the observations later than begin_timestamp. | |
| 858 DCHECK_GE(observations_.size(), weighted_observations.size()); | |
| 859 | |
| 860 double desired_weight = percentile / 100.0 * total_weight; | |
| 861 | |
| 862 double cumulative_weight_seen_so_far = 0.0; | |
| 863 for (const auto& weighted_observation : weighted_observations) { | |
| 864 cumulative_weight_seen_so_far += weighted_observation.weight; | |
| 865 | |
| 866 if (cumulative_weight_seen_so_far >= desired_weight) { | |
| 867 *result = weighted_observation.value; | |
| 868 return true; | |
| 869 } | |
| 870 } | |
| 871 | |
| 872 // Computation may reach here due to floating point errors. This may happen | |
| 873 // if |percentile| was 100 (or close to 100), and |desired_weight| was | |
| 874 // slightly larger than |total_weight| (due to floating point errors). | |
| 875 // In this case, we return the highest |value| among all observations. | |
| 876 // This is same as value of the last observation in the sorted vector. | |
| 877 *result = weighted_observations.at(weighted_observations.size() - 1).value; | |
| 878 return true; | |
| 879 } | |
| 880 | |
| 881 NetworkQualityEstimator::NetworkID | 788 NetworkQualityEstimator::NetworkID |
| 882 NetworkQualityEstimator::GetCurrentNetworkID() const { | 789 NetworkQualityEstimator::GetCurrentNetworkID() const { |
| 883 DCHECK(thread_checker_.CalledOnValidThread()); | 790 DCHECK(thread_checker_.CalledOnValidThread()); |
| 884 | 791 |
| 885 // TODO(tbansal): crbug.com/498068 Add NetworkQualityEstimatorAndroid class | 792 // TODO(tbansal): crbug.com/498068 Add NetworkQualityEstimatorAndroid class |
| 886 // that overrides this method on the Android platform. | 793 // that overrides this method on the Android platform. |
| 887 | 794 |
| 888 // It is possible that the connection type changed between when | 795 // It is possible that the connection type changed between when |
| 889 // GetConnectionType() was called and when the API to determine the | 796 // GetConnectionType() was called and when the API to determine the |
| 890 // network name was called. Check if that happened and retry until the | 797 // network name was called. Check if that happened and retry until the |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 931 // If the network name is unavailable, caching should not be performed. | 838 // If the network name is unavailable, caching should not be performed. |
| 932 if (current_network_id_.id.empty()) | 839 if (current_network_id_.id.empty()) |
| 933 return false; | 840 return false; |
| 934 | 841 |
| 935 CachedNetworkQualities::const_iterator it = | 842 CachedNetworkQualities::const_iterator it = |
| 936 cached_network_qualities_.find(current_network_id_); | 843 cached_network_qualities_.find(current_network_id_); |
| 937 | 844 |
| 938 if (it == cached_network_qualities_.end()) | 845 if (it == cached_network_qualities_.end()) |
| 939 return false; | 846 return false; |
| 940 | 847 |
| 941 NetworkQuality network_quality(it->second.network_quality()); | 848 nqe::internal::NetworkQuality network_quality(it->second.network_quality()); |
| 942 | 849 |
| 943 DCHECK_NE(InvalidRTT(), network_quality.rtt()); | 850 DCHECK_NE(nqe::internal::InvalidRTT(), network_quality.rtt()); |
| 944 DCHECK_NE(kInvalidThroughput, network_quality.downstream_throughput_kbps()); | 851 DCHECK_NE(nqe::internal::kInvalidThroughput, |
| 852 network_quality.downstream_throughput_kbps()); |
| 945 | 853 |
| 946 ThroughputObservation througphput_observation( | 854 ThroughputObservation througphput_observation( |
| 947 network_quality.downstream_throughput_kbps(), base::TimeTicks::Now(), | 855 network_quality.downstream_throughput_kbps(), base::TimeTicks::Now(), |
| 948 CACHED_ESTIMATE); | 856 NETWORK_QUALITY_OBSERVATION_SOURCE_CACHED_ESTIMATE); |
| 949 downstream_throughput_kbps_observations_.AddObservation( | 857 downstream_throughput_kbps_observations_.AddObservation( |
| 950 througphput_observation); | 858 througphput_observation); |
| 951 NotifyObserversOfThroughput(througphput_observation); | 859 NotifyObserversOfThroughput(througphput_observation); |
| 952 | 860 |
| 953 RttObservation rtt_observation(network_quality.rtt(), base::TimeTicks::Now(), | 861 RttObservation rtt_observation( |
| 954 CACHED_ESTIMATE); | 862 network_quality.rtt(), base::TimeTicks::Now(), |
| 863 NETWORK_QUALITY_OBSERVATION_SOURCE_CACHED_ESTIMATE); |
| 955 rtt_observations_.AddObservation(rtt_observation); | 864 rtt_observations_.AddObservation(rtt_observation); |
| 956 NotifyObserversOfRTT(rtt_observation); | 865 NotifyObserversOfRTT(rtt_observation); |
| 957 | 866 |
| 958 return true; | 867 return true; |
| 959 } | 868 } |
| 960 | 869 |
| 961 void NetworkQualityEstimator::OnUpdatedEstimateAvailable() { | 870 void NetworkQualityEstimator::OnUpdatedEstimateAvailable() { |
| 962 DCHECK(thread_checker_.CalledOnValidThread()); | 871 DCHECK(thread_checker_.CalledOnValidThread()); |
| 963 DCHECK(external_estimate_provider_); | 872 DCHECK(external_estimate_provider_); |
| 964 | 873 |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1016 } | 925 } |
| 1017 | 926 |
| 1018 RecordExternalEstimateProviderMetrics( | 927 RecordExternalEstimateProviderMetrics( |
| 1019 EXTERNAL_ESTIMATE_PROVIDER_STATUS_QUERY_SUCCESSFUL); | 928 EXTERNAL_ESTIMATE_PROVIDER_STATUS_QUERY_SUCCESSFUL); |
| 1020 base::TimeDelta rtt; | 929 base::TimeDelta rtt; |
| 1021 if (external_estimate_provider_->GetRTT(&rtt)) { | 930 if (external_estimate_provider_->GetRTT(&rtt)) { |
| 1022 RecordExternalEstimateProviderMetrics( | 931 RecordExternalEstimateProviderMetrics( |
| 1023 EXTERNAL_ESTIMATE_PROVIDER_STATUS_RTT_AVAILABLE); | 932 EXTERNAL_ESTIMATE_PROVIDER_STATUS_RTT_AVAILABLE); |
| 1024 UMA_HISTOGRAM_TIMES("NQE.ExternalEstimateProvider.RTT", rtt); | 933 UMA_HISTOGRAM_TIMES("NQE.ExternalEstimateProvider.RTT", rtt); |
| 1025 rtt_observations_.AddObservation( | 934 rtt_observations_.AddObservation( |
| 1026 RttObservation(rtt, base::TimeTicks::Now(), EXTERNAL_ESTIMATE)); | 935 RttObservation(rtt, base::TimeTicks::Now(), |
| 936 NETWORK_QUALITY_OBSERVATION_SOURCE_EXTERNAL_ESTIMATE)); |
| 1027 } | 937 } |
| 1028 | 938 |
| 1029 int32_t downstream_throughput_kbps; | 939 int32_t downstream_throughput_kbps; |
| 1030 if (external_estimate_provider_->GetDownstreamThroughputKbps( | 940 if (external_estimate_provider_->GetDownstreamThroughputKbps( |
| 1031 &downstream_throughput_kbps)) { | 941 &downstream_throughput_kbps)) { |
| 1032 RecordExternalEstimateProviderMetrics( | 942 RecordExternalEstimateProviderMetrics( |
| 1033 EXTERNAL_ESTIMATE_PROVIDER_STATUS_DOWNLINK_BANDWIDTH_AVAILABLE); | 943 EXTERNAL_ESTIMATE_PROVIDER_STATUS_DOWNLINK_BANDWIDTH_AVAILABLE); |
| 1034 UMA_HISTOGRAM_COUNTS("NQE.ExternalEstimateProvider.DownlinkBandwidth", | 944 UMA_HISTOGRAM_COUNTS("NQE.ExternalEstimateProvider.DownlinkBandwidth", |
| 1035 downstream_throughput_kbps); | 945 downstream_throughput_kbps); |
| 1036 downstream_throughput_kbps_observations_.AddObservation( | 946 downstream_throughput_kbps_observations_.AddObservation( |
| 1037 ThroughputObservation(downstream_throughput_kbps, | 947 ThroughputObservation( |
| 1038 base::TimeTicks::Now(), EXTERNAL_ESTIMATE)); | 948 downstream_throughput_kbps, base::TimeTicks::Now(), |
| 949 NETWORK_QUALITY_OBSERVATION_SOURCE_EXTERNAL_ESTIMATE)); |
| 1039 } | 950 } |
| 1040 } | 951 } |
| 1041 | 952 |
| 1042 void NetworkQualityEstimator::CacheNetworkQualityEstimate() { | 953 void NetworkQualityEstimator::CacheNetworkQualityEstimate() { |
| 1043 DCHECK(thread_checker_.CalledOnValidThread()); | 954 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1044 DCHECK_LE(cached_network_qualities_.size(), | 955 DCHECK_LE(cached_network_qualities_.size(), |
| 1045 static_cast<size_t>(kMaximumNetworkQualityCacheSize)); | 956 static_cast<size_t>(kMaximumNetworkQualityCacheSize)); |
| 1046 | 957 |
| 1047 // If the network name is unavailable, caching should not be performed. | 958 // If the network name is unavailable, caching should not be performed. |
| 1048 if (current_network_id_.id.empty()) | 959 if (current_network_id_.id.empty()) |
| 1049 return; | 960 return; |
| 1050 | 961 |
| 1051 base::TimeDelta rtt = InvalidRTT(); | 962 base::TimeDelta rtt = nqe::internal::InvalidRTT(); |
| 1052 int32_t downlink_throughput_kbps = kInvalidThroughput; | 963 int32_t downlink_throughput_kbps = nqe::internal::kInvalidThroughput; |
| 1053 | 964 |
| 1054 if (!GetURLRequestRTTEstimate(&rtt) || | 965 if (!GetURLRequestRTTEstimate(&rtt) || |
| 1055 !GetDownlinkThroughputKbpsEstimate(&downlink_throughput_kbps)) { | 966 !GetDownlinkThroughputKbpsEstimate(&downlink_throughput_kbps)) { |
| 1056 return; | 967 return; |
| 1057 } | 968 } |
| 1058 | 969 |
| 1059 NetworkQuality network_quality = | 970 nqe::internal::NetworkQuality network_quality = |
| 1060 NetworkQuality(rtt, downlink_throughput_kbps); | 971 nqe::internal::NetworkQuality(rtt, downlink_throughput_kbps); |
| 1061 | 972 |
| 1062 if (cached_network_qualities_.size() == kMaximumNetworkQualityCacheSize) { | 973 if (cached_network_qualities_.size() == kMaximumNetworkQualityCacheSize) { |
| 1063 // Remove the oldest entry. | 974 // Remove the oldest entry. |
| 1064 CachedNetworkQualities::iterator oldest_entry_iterator = | 975 CachedNetworkQualities::iterator oldest_entry_iterator = |
| 1065 cached_network_qualities_.begin(); | 976 cached_network_qualities_.begin(); |
| 1066 | 977 |
| 1067 for (CachedNetworkQualities::iterator it = | 978 for (CachedNetworkQualities::iterator it = |
| 1068 cached_network_qualities_.begin(); | 979 cached_network_qualities_.begin(); |
| 1069 it != cached_network_qualities_.end(); ++it) { | 980 it != cached_network_qualities_.end(); ++it) { |
| 1070 if ((it->second).OlderThan(oldest_entry_iterator->second)) | 981 if ((it->second).OlderThan(oldest_entry_iterator->second)) |
| 1071 oldest_entry_iterator = it; | 982 oldest_entry_iterator = it; |
| 1072 } | 983 } |
| 1073 cached_network_qualities_.erase(oldest_entry_iterator); | 984 cached_network_qualities_.erase(oldest_entry_iterator); |
| 1074 } | 985 } |
| 1075 DCHECK_LT(cached_network_qualities_.size(), | 986 DCHECK_LT(cached_network_qualities_.size(), |
| 1076 static_cast<size_t>(kMaximumNetworkQualityCacheSize)); | 987 static_cast<size_t>(kMaximumNetworkQualityCacheSize)); |
| 1077 | 988 |
| 1078 cached_network_qualities_.insert(std::make_pair( | 989 cached_network_qualities_.insert( |
| 1079 current_network_id_, CachedNetworkQuality(network_quality))); | 990 std::make_pair(current_network_id_, |
| 991 nqe::internal::CachedNetworkQuality(network_quality))); |
| 1080 DCHECK_LE(cached_network_qualities_.size(), | 992 DCHECK_LE(cached_network_qualities_.size(), |
| 1081 static_cast<size_t>(kMaximumNetworkQualityCacheSize)); | 993 static_cast<size_t>(kMaximumNetworkQualityCacheSize)); |
| 1082 } | 994 } |
| 1083 | 995 |
| 1084 void NetworkQualityEstimator::OnUpdatedRTTAvailable( | 996 void NetworkQualityEstimator::OnUpdatedRTTAvailable( |
| 1085 SocketPerformanceWatcherFactory::Protocol protocol, | 997 SocketPerformanceWatcherFactory::Protocol protocol, |
| 1086 const base::TimeDelta& rtt) { | 998 const base::TimeDelta& rtt) { |
| 1087 DCHECK(thread_checker_.CalledOnValidThread()); | 999 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1088 | 1000 |
| 1089 switch (protocol) { | 1001 switch (protocol) { |
| 1090 case SocketPerformanceWatcherFactory::PROTOCOL_TCP: | 1002 case SocketPerformanceWatcherFactory::PROTOCOL_TCP: |
| 1091 NotifyObserversOfRTT(RttObservation(rtt, base::TimeTicks::Now(), TCP)); | 1003 NotifyObserversOfRTT(RttObservation( |
| 1004 rtt, base::TimeTicks::Now(), NETWORK_QUALITY_OBSERVATION_SOURCE_TCP)); |
| 1092 return; | 1005 return; |
| 1093 case SocketPerformanceWatcherFactory::PROTOCOL_QUIC: | 1006 case SocketPerformanceWatcherFactory::PROTOCOL_QUIC: |
| 1094 NotifyObserversOfRTT(RttObservation(rtt, base::TimeTicks::Now(), QUIC)); | 1007 NotifyObserversOfRTT( |
| 1008 RttObservation(rtt, base::TimeTicks::Now(), |
| 1009 NETWORK_QUALITY_OBSERVATION_SOURCE_QUIC)); |
| 1095 return; | 1010 return; |
| 1096 default: | 1011 default: |
| 1097 NOTREACHED(); | 1012 NOTREACHED(); |
| 1098 } | 1013 } |
| 1099 } | 1014 } |
| 1100 | 1015 |
| 1101 void NetworkQualityEstimator::NotifyObserversOfRTT( | 1016 void NetworkQualityEstimator::NotifyObserversOfRTT( |
| 1102 const RttObservation& observation) { | 1017 const RttObservation& observation) { |
| 1103 FOR_EACH_OBSERVER( | 1018 FOR_EACH_OBSERVER( |
| 1104 RTTObserver, rtt_observer_list_, | 1019 RTTObserver, rtt_observer_list_, |
| 1105 OnRTTObservation(observation.value.InMilliseconds(), | 1020 OnRTTObservation(observation.value.InMilliseconds(), |
| 1106 observation.timestamp, observation.source)); | 1021 observation.timestamp, observation.source)); |
| 1107 } | 1022 } |
| 1108 | 1023 |
| 1109 void NetworkQualityEstimator::NotifyObserversOfThroughput( | 1024 void NetworkQualityEstimator::NotifyObserversOfThroughput( |
| 1110 const ThroughputObservation& observation) { | 1025 const ThroughputObservation& observation) { |
| 1111 FOR_EACH_OBSERVER( | 1026 FOR_EACH_OBSERVER( |
| 1112 ThroughputObserver, throughput_observer_list_, | 1027 ThroughputObserver, throughput_observer_list_, |
| 1113 OnThroughputObservation(observation.value, observation.timestamp, | 1028 OnThroughputObservation(observation.value, observation.timestamp, |
| 1114 observation.source)); | 1029 observation.source)); |
| 1115 } | 1030 } |
| 1116 | 1031 |
| 1117 NetworkQualityEstimator::CachedNetworkQuality::CachedNetworkQuality( | |
| 1118 const NetworkQuality& network_quality) | |
| 1119 : last_update_time_(base::TimeTicks::Now()), | |
| 1120 network_quality_(network_quality) {} | |
| 1121 | |
| 1122 NetworkQualityEstimator::CachedNetworkQuality::CachedNetworkQuality( | |
| 1123 const CachedNetworkQuality& other) | |
| 1124 : last_update_time_(other.last_update_time_), | |
| 1125 network_quality_(other.network_quality_) {} | |
| 1126 | |
| 1127 NetworkQualityEstimator::CachedNetworkQuality::~CachedNetworkQuality() {} | |
| 1128 | |
| 1129 bool NetworkQualityEstimator::CachedNetworkQuality::OlderThan( | |
| 1130 const CachedNetworkQuality& cached_network_quality) const { | |
| 1131 return last_update_time_ < cached_network_quality.last_update_time_; | |
| 1132 } | |
| 1133 | |
| 1134 NetworkQualityEstimator::NetworkQuality::NetworkQuality() | |
| 1135 : NetworkQuality(NetworkQualityEstimator::InvalidRTT(), | |
| 1136 NetworkQualityEstimator::kInvalidThroughput) {} | |
| 1137 | |
| 1138 NetworkQualityEstimator::NetworkQuality::NetworkQuality( | |
| 1139 const base::TimeDelta& rtt, | |
| 1140 int32_t downstream_throughput_kbps) | |
| 1141 : rtt_(rtt), downstream_throughput_kbps_(downstream_throughput_kbps) { | |
| 1142 DCHECK_GE(rtt_, base::TimeDelta()); | |
| 1143 DCHECK_GE(downstream_throughput_kbps_, 0); | |
| 1144 } | |
| 1145 | |
| 1146 NetworkQualityEstimator::NetworkQuality::NetworkQuality( | |
| 1147 const NetworkQuality& other) | |
| 1148 : NetworkQuality(other.rtt_, other.downstream_throughput_kbps_) {} | |
| 1149 | |
| 1150 NetworkQualityEstimator::NetworkQuality::~NetworkQuality() {} | |
| 1151 | |
| 1152 NetworkQualityEstimator::NetworkQuality& | |
| 1153 NetworkQualityEstimator::NetworkQuality::operator=( | |
| 1154 const NetworkQuality& other) { | |
| 1155 rtt_ = other.rtt_; | |
| 1156 downstream_throughput_kbps_ = other.downstream_throughput_kbps_; | |
| 1157 return *this; | |
| 1158 } | |
| 1159 | |
| 1160 } // namespace net | 1032 } // namespace net |
| OLD | NEW |