OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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/throughput_analyzer.h" | 5 #include "net/nqe/throughput_analyzer.h" |
6 | 6 |
7 #include <cmath> | 7 #include <cmath> |
8 | 8 |
9 #include "base/location.h" | 9 #include "base/location.h" |
10 #include "base/single_thread_task_runner.h" | 10 #include "base/single_thread_task_runner.h" |
11 #include "net/base/network_activity_monitor.h" | 11 #include "net/base/network_activity_monitor.h" |
12 #include "net/base/url_util.h" | 12 #include "net/base/url_util.h" |
| 13 #include "net/nqe/network_quality_estimator_params.h" |
13 #include "net/url_request/url_request.h" | 14 #include "net/url_request/url_request.h" |
14 | 15 |
15 #if defined(OS_ANDROID) | 16 #if defined(OS_ANDROID) |
16 #include "net/android/traffic_stats.h" | 17 #include "net/android/traffic_stats.h" |
17 #endif // OS_ANDROID | 18 #endif // OS_ANDROID |
18 | 19 |
19 namespace net { | 20 namespace net { |
20 | 21 |
21 namespace { | 22 namespace { |
22 | 23 |
23 // Maximum number of accuracy degrading requests, and requests that do not | 24 // Maximum number of accuracy degrading requests, and requests that do not |
24 // degrade accuracy held in the memory. | 25 // degrade accuracy held in the memory. |
25 static const size_t kMaxRequestsSize = 300; | 26 static const size_t kMaxRequestsSize = 300; |
26 | 27 |
27 // Tiny transfer sizes may give inaccurate throughput results. | 28 // Tiny transfer sizes may give inaccurate throughput results. |
28 // Minimum size of the transfer over which the throughput is computed. | 29 // Minimum size of the transfer over which the throughput is computed. |
29 static const int kMinTransferSizeInBits = 32 * 8 * 1000; | 30 static const int kMinTransferSizeInBits = 32 * 8 * 1000; |
30 | 31 |
31 } // namespace | 32 } // namespace |
32 | 33 |
33 namespace nqe { | 34 namespace nqe { |
34 | 35 |
35 namespace internal { | 36 namespace internal { |
36 | 37 |
37 ThroughputAnalyzer::ThroughputAnalyzer( | 38 ThroughputAnalyzer::ThroughputAnalyzer( |
| 39 const NetworkQualityEstimatorParams* params, |
38 scoped_refptr<base::SingleThreadTaskRunner> task_runner, | 40 scoped_refptr<base::SingleThreadTaskRunner> task_runner, |
39 ThroughputObservationCallback throughput_observation_callback, | 41 ThroughputObservationCallback throughput_observation_callback, |
40 bool use_local_host_requests_for_tests, | 42 bool use_local_host_requests_for_tests, |
41 bool use_smaller_responses_for_tests) | 43 bool use_smaller_responses_for_tests) |
42 : task_runner_(task_runner), | 44 : params_(params), |
| 45 task_runner_(task_runner), |
43 throughput_observation_callback_(throughput_observation_callback), | 46 throughput_observation_callback_(throughput_observation_callback), |
44 last_connection_change_(base::TimeTicks::Now()), | 47 last_connection_change_(base::TimeTicks::Now()), |
45 window_start_time_(base::TimeTicks()), | 48 window_start_time_(base::TimeTicks()), |
46 bits_received_at_window_start_(0), | 49 bits_received_at_window_start_(0), |
47 disable_throughput_measurements_(false), | 50 disable_throughput_measurements_(false), |
48 use_localhost_requests_for_tests_(use_local_host_requests_for_tests), | 51 use_localhost_requests_for_tests_(use_local_host_requests_for_tests), |
49 use_small_responses_for_tests_(use_smaller_responses_for_tests) { | 52 use_small_responses_for_tests_(use_smaller_responses_for_tests) { |
| 53 DCHECK(params_); |
50 DCHECK(task_runner_); | 54 DCHECK(task_runner_); |
51 DCHECK(!IsCurrentlyTrackingThroughput()); | 55 DCHECK(!IsCurrentlyTrackingThroughput()); |
52 } | 56 } |
53 | 57 |
54 ThroughputAnalyzer::~ThroughputAnalyzer() { | 58 ThroughputAnalyzer::~ThroughputAnalyzer() { |
55 DCHECK(thread_checker_.CalledOnValidThread()); | 59 DCHECK(thread_checker_.CalledOnValidThread()); |
56 } | 60 } |
57 | 61 |
58 void ThroughputAnalyzer::MaybeStartThroughputObservationWindow() { | 62 void ThroughputAnalyzer::MaybeStartThroughputObservationWindow() { |
59 DCHECK(thread_checker_.CalledOnValidThread()); | 63 DCHECK(thread_checker_.CalledOnValidThread()); |
60 | 64 |
61 if (disable_throughput_measurements_) | 65 if (disable_throughput_measurements_) |
62 return; | 66 return; |
63 | 67 |
64 // Throughput observation window can be started only if no accuracy degrading | 68 // Throughput observation window can be started only if no accuracy degrading |
65 // requests are currently active, the observation window is not already | 69 // requests are currently active, the observation window is not already |
66 // started, and there is at least one active request that does not degrade | 70 // started, and there is at least one active request that does not degrade |
67 // throughput computation accuracy. | 71 // throughput computation accuracy. |
68 if (accuracy_degrading_requests_.size() > 0 || | 72 if (accuracy_degrading_requests_.size() > 0 || |
69 IsCurrentlyTrackingThroughput() || requests_.size() <= 0) { | 73 IsCurrentlyTrackingThroughput() || |
| 74 requests_.size() < params_->throughput_min_requests_in_flight()) { |
70 return; | 75 return; |
71 } | 76 } |
72 window_start_time_ = base::TimeTicks::Now(); | 77 window_start_time_ = base::TimeTicks::Now(); |
73 bits_received_at_window_start_ = GetBitsReceived(); | 78 bits_received_at_window_start_ = GetBitsReceived(); |
74 } | 79 } |
75 | 80 |
76 void ThroughputAnalyzer::EndThroughputObservationWindow() { | 81 void ThroughputAnalyzer::EndThroughputObservationWindow() { |
77 DCHECK(thread_checker_.CalledOnValidThread()); | 82 DCHECK(thread_checker_.CalledOnValidThread()); |
78 | 83 |
79 // Mark the throughput observation window as stopped by resetting the window | 84 // Mark the throughput observation window as stopped by resetting the window |
80 // parameters. | 85 // parameters. |
81 window_start_time_ = base::TimeTicks(); | 86 window_start_time_ = base::TimeTicks(); |
82 bits_received_at_window_start_ = 0; | 87 bits_received_at_window_start_ = 0; |
83 } | 88 } |
84 | 89 |
85 bool ThroughputAnalyzer::IsCurrentlyTrackingThroughput() const { | 90 bool ThroughputAnalyzer::IsCurrentlyTrackingThroughput() const { |
86 DCHECK(thread_checker_.CalledOnValidThread()); | 91 DCHECK(thread_checker_.CalledOnValidThread()); |
87 | 92 |
88 if (window_start_time_.is_null()) | 93 if (window_start_time_.is_null()) |
89 return false; | 94 return false; |
90 | 95 |
91 // If the throughput observation window is running, then at least one request | 96 // If the throughput observation window is running, then at least one request |
92 // that does not degrade throughput computation accuracy should be active. | 97 // that does not degrade throughput computation accuracy should be active. |
93 DCHECK_GT(requests_.size(), 0U); | 98 DCHECK_GT(requests_.size(), 0U); |
94 | 99 |
95 // If the throughput observation window is running, then no accuracy degrading | 100 // If the throughput observation window is running, then no accuracy degrading |
96 // requests should be currently active. | 101 // requests should be currently active. |
97 DCHECK_EQ(0U, accuracy_degrading_requests_.size()); | 102 DCHECK_EQ(0U, accuracy_degrading_requests_.size()); |
98 | 103 |
| 104 DCHECK_LE(params_->throughput_min_requests_in_flight(), requests_.size()); |
| 105 |
99 return true; | 106 return true; |
100 } | 107 } |
101 | 108 |
102 void ThroughputAnalyzer::NotifyStartTransaction(const URLRequest& request) { | 109 void ThroughputAnalyzer::NotifyStartTransaction(const URLRequest& request) { |
103 DCHECK(thread_checker_.CalledOnValidThread()); | 110 DCHECK(thread_checker_.CalledOnValidThread()); |
104 | 111 |
105 if (disable_throughput_measurements_) | 112 if (disable_throughput_measurements_) |
106 return; | 113 return; |
107 | 114 |
108 const bool degrades_accuracy = DegradesAccuracy(request); | 115 const bool degrades_accuracy = DegradesAccuracy(request); |
(...skipping 25 matching lines...) Expand all Loading... |
134 | 141 |
135 // Return early if the |request| is not present in the collections of | 142 // Return early if the |request| is not present in the collections of |
136 // requests. This may happen when a completed request is later destroyed. | 143 // requests. This may happen when a completed request is later destroyed. |
137 if (requests_.find(&request) == requests_.end() && | 144 if (requests_.find(&request) == requests_.end() && |
138 accuracy_degrading_requests_.find(&request) == | 145 accuracy_degrading_requests_.find(&request) == |
139 accuracy_degrading_requests_.end()) { | 146 accuracy_degrading_requests_.end()) { |
140 return; | 147 return; |
141 } | 148 } |
142 | 149 |
143 int32_t downstream_kbps; | 150 int32_t downstream_kbps; |
144 if (MayBeGetThroughputObservation(&downstream_kbps)) { | 151 if (MaybeGetThroughputObservation(&downstream_kbps)) { |
145 // Notify the provided callback. | 152 // Notify the provided callback. |
146 task_runner_->PostTask( | 153 task_runner_->PostTask( |
147 FROM_HERE, | 154 FROM_HERE, |
148 base::Bind(throughput_observation_callback_, downstream_kbps)); | 155 base::Bind(throughput_observation_callback_, downstream_kbps)); |
149 } | 156 } |
150 | 157 |
151 // Try to remove the request from either |accuracy_degrading_requests_| or | 158 // Try to remove the request from either |accuracy_degrading_requests_| or |
152 // |requests_|, since it is no longer active. | 159 // |requests_|, since it is no longer active. |
153 if (accuracy_degrading_requests_.erase(&request) == 1u) { | 160 if (accuracy_degrading_requests_.erase(&request) == 1u) { |
154 // |request| cannot be in both |accuracy_degrading_requests_| and | 161 // |request| cannot be in both |accuracy_degrading_requests_| and |
155 // |requests_| at the same time. | 162 // |requests_| at the same time. |
156 DCHECK(requests_.end() == requests_.find(&request)); | 163 DCHECK(requests_.end() == requests_.find(&request)); |
157 | 164 |
158 // If a request that degraded the accuracy of throughput computation has | 165 // If a request that degraded the accuracy of throughput computation has |
159 // completed, then it may be possible to start the tracking window. | 166 // completed, then it may be possible to start the tracking window. |
160 MaybeStartThroughputObservationWindow(); | 167 MaybeStartThroughputObservationWindow(); |
161 return; | 168 return; |
162 } | 169 } |
163 | 170 |
164 if (requests_.erase(&request) == 1u) { | 171 if (requests_.erase(&request) == 1u) { |
165 // If there is no network activity, stop tracking throughput to prevent | 172 // If there is no network activity, stop tracking throughput to prevent |
166 // recording of any observations. | 173 // recording of any observations. |
167 if (requests_.size() == 0) | 174 if (requests_.size() < params_->throughput_min_requests_in_flight()) |
168 EndThroughputObservationWindow(); | 175 EndThroughputObservationWindow(); |
169 return; | 176 return; |
170 } | 177 } |
171 // |request| must be either in |accuracy_degrading_requests_| or |requests_|. | 178 // |request| must be either in |accuracy_degrading_requests_| or |requests_|. |
172 NOTREACHED(); | 179 NOTREACHED(); |
173 } | 180 } |
174 | 181 |
175 bool ThroughputAnalyzer::MayBeGetThroughputObservation( | 182 bool ThroughputAnalyzer::MaybeGetThroughputObservation( |
176 int32_t* downstream_kbps) { | 183 int32_t* downstream_kbps) { |
177 DCHECK(thread_checker_.CalledOnValidThread()); | 184 DCHECK(thread_checker_.CalledOnValidThread()); |
178 DCHECK(downstream_kbps); | 185 DCHECK(downstream_kbps); |
179 | 186 |
180 if (disable_throughput_measurements_) | 187 if (disable_throughput_measurements_) |
181 return false; | 188 return false; |
182 | 189 |
183 // Return early if the window that records downstream throughput is currently | 190 // Return early if the window that records downstream throughput is currently |
184 // inactive because throughput observations can be taken only when the window | 191 // inactive because throughput observations can be taken only when the window |
185 // is active. | 192 // is active. |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
290 // TODO(tbansal): crbug.com/609174 Add UMA to record how frequently this | 297 // TODO(tbansal): crbug.com/609174 Add UMA to record how frequently this |
291 // happens. | 298 // happens. |
292 } | 299 } |
293 } | 300 } |
294 | 301 |
295 } // namespace internal | 302 } // namespace internal |
296 | 303 |
297 } // namespace nqe | 304 } // namespace nqe |
298 | 305 |
299 } // namespace net | 306 } // namespace net |
OLD | NEW |