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

Side by Side Diff: content/browser/loader/resource_scheduler.cc

Issue 1285863003: ResourceScheduler: remove dependency on ResourceRequestInfo and request_id (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@lkgr
Patch Set: Changes suggested by davidben@ Created 5 years, 4 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 <set> 5 #include <set>
6 6
7 #include "content/browser/loader/resource_scheduler.h" 7 #include "content/browser/loader/resource_scheduler.h"
8 8
9 #include "base/metrics/field_trial.h" 9 #include "base/metrics/field_trial.h"
10 #include "base/metrics/histogram.h" 10 #include "base/metrics/histogram.h"
11 #include "base/stl_util.h" 11 #include "base/stl_util.h"
12 #include "base/strings/string_number_conversions.h" 12 #include "base/strings/string_number_conversions.h"
13 #include "base/strings/string_piece.h" 13 #include "base/strings/string_piece.h"
14 #include "base/supports_user_data.h"
14 #include "base/time/time.h" 15 #include "base/time/time.h"
15 #include "content/common/resource_messages.h" 16 #include "content/common/resource_messages.h"
16 #include "content/browser/loader/resource_message_delegate.h"
17 #include "content/public/browser/resource_controller.h" 17 #include "content/public/browser/resource_controller.h"
18 #include "content/public/browser/resource_request_info.h" 18 #include "content/public/browser/resource_request_info.h"
19 #include "content/public/browser/resource_throttle.h" 19 #include "content/public/browser/resource_throttle.h"
20 #include "ipc/ipc_message_macros.h"
21 #include "net/base/host_port_pair.h" 20 #include "net/base/host_port_pair.h"
22 #include "net/base/load_flags.h" 21 #include "net/base/load_flags.h"
23 #include "net/base/request_priority.h" 22 #include "net/base/request_priority.h"
24 #include "net/http/http_server_properties.h" 23 #include "net/http/http_server_properties.h"
25 #include "net/url_request/url_request.h" 24 #include "net/url_request/url_request.h"
26 #include "net/url_request/url_request_context.h" 25 #include "net/url_request/url_request_context.h"
27 26
28 namespace content { 27 namespace content {
29 28
30 namespace { 29 namespace {
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
103 return priority > other.priority; 102 return priority > other.priority;
104 return intra_priority > other.intra_priority; 103 return intra_priority > other.intra_priority;
105 } 104 }
106 105
107 net::RequestPriority priority; 106 net::RequestPriority priority;
108 int intra_priority; 107 int intra_priority;
109 }; 108 };
110 109
111 class ResourceScheduler::RequestQueue { 110 class ResourceScheduler::RequestQueue {
112 public: 111 public:
113 typedef std::multiset<ScheduledResourceRequest*, ScheduledResourceSorter> 112 typedef std::multiset<ScheduledResourceRequestImpl*, ScheduledResourceSorter>
114 NetQueue; 113 NetQueue;
115 114
116 RequestQueue() : fifo_ordering_ids_(0) {} 115 RequestQueue() : fifo_ordering_ids_(0) {}
117 ~RequestQueue() {} 116 ~RequestQueue() {}
118 117
119 // Adds |request| to the queue with given |priority|. 118 // Adds |request| to the queue with given |priority|.
120 void Insert(ScheduledResourceRequest* request); 119 void Insert(ScheduledResourceRequestImpl* request);
121 120
122 // Removes |request| from the queue. 121 // Removes |request| from the queue.
123 void Erase(ScheduledResourceRequest* request) { 122 void Erase(ScheduledResourceRequestImpl* request) {
124 PointerMap::iterator it = pointers_.find(request); 123 PointerMap::iterator it = pointers_.find(request);
125 DCHECK(it != pointers_.end()); 124 DCHECK(it != pointers_.end());
126 if (it == pointers_.end()) 125 if (it == pointers_.end())
127 return; 126 return;
128 queue_.erase(it->second); 127 queue_.erase(it->second);
129 pointers_.erase(it); 128 pointers_.erase(it);
130 } 129 }
131 130
132 NetQueue::iterator GetNextHighestIterator() { 131 NetQueue::iterator GetNextHighestIterator() {
133 return queue_.begin(); 132 return queue_.begin();
134 } 133 }
135 134
136 NetQueue::iterator End() { 135 NetQueue::iterator End() {
137 return queue_.end(); 136 return queue_.end();
138 } 137 }
139 138
140 // Returns true if |request| is queued. 139 // Returns true if |request| is queued.
141 bool IsQueued(ScheduledResourceRequest* request) const { 140 bool IsQueued(ScheduledResourceRequestImpl* request) const {
142 return ContainsKey(pointers_, request); 141 return ContainsKey(pointers_, request);
143 } 142 }
144 143
145 // Returns true if no requests are queued. 144 // Returns true if no requests are queued.
146 bool IsEmpty() const { return queue_.size() == 0; } 145 bool IsEmpty() const { return queue_.size() == 0; }
147 146
148 private: 147 private:
149 typedef std::map<ScheduledResourceRequest*, NetQueue::iterator> PointerMap; 148 typedef std::map<ScheduledResourceRequestImpl*, NetQueue::iterator>
149 PointerMap;
150 150
151 uint32 MakeFifoOrderingId() { 151 uint32 MakeFifoOrderingId() {
152 fifo_ordering_ids_ += 1; 152 fifo_ordering_ids_ += 1;
153 return fifo_ordering_ids_; 153 return fifo_ordering_ids_;
154 } 154 }
155 155
156 // Used to create an ordering ID for scheduled resources so that resources 156 // Used to create an ordering ID for scheduled resources so that resources
157 // with same priority/intra_priority stay in fifo order. 157 // with same priority/intra_priority stay in fifo order.
158 uint32 fifo_ordering_ids_; 158 uint32 fifo_ordering_ids_;
159 159
160 NetQueue queue_; 160 NetQueue queue_;
161 PointerMap pointers_; 161 PointerMap pointers_;
162 }; 162 };
163 163
164 // This is the handle we return to the ResourceDispatcherHostImpl so it can 164 // This is the handle we return to the ResourceDispatcherHostImpl so it can
165 // interact with the request. 165 // interact with the request.
166 class ResourceScheduler::ScheduledResourceRequest 166 class ResourceScheduler::ScheduledResourceRequestImpl
167 : public ResourceMessageDelegate, 167 : public ScheduledResourceRequest {
168 public ResourceThrottle {
169 public: 168 public:
170 ScheduledResourceRequest(const ClientId& client_id, 169 ScheduledResourceRequestImpl(const ClientId& client_id,
171 net::URLRequest* request, 170 net::URLRequest* request,
172 ResourceScheduler* scheduler, 171 ResourceScheduler* scheduler,
173 const RequestPriorityParams& priority) 172 const RequestPriorityParams& priority,
174 : ResourceMessageDelegate(request), 173 bool is_async)
175 client_id_(client_id), 174 : client_id_(client_id),
176 client_state_on_creation_(scheduler->GetClientState(client_id_)), 175 client_state_on_creation_(scheduler->GetClientState(client_id_)),
177 request_(request), 176 request_(request),
178 ready_(false), 177 ready_(false),
179 deferred_(false), 178 deferred_(false),
179 is_async_(is_async),
180 classification_(NORMAL_REQUEST), 180 classification_(NORMAL_REQUEST),
181 scheduler_(scheduler), 181 scheduler_(scheduler),
182 priority_(priority), 182 priority_(priority),
183 fifo_ordering_(0) { 183 fifo_ordering_(0) {
184 request_->SetUserData(kUserDataKey, new UnownedPointer(this));
184 } 185 }
185 186
186 ~ScheduledResourceRequest() override { scheduler_->RemoveRequest(this); } 187 ~ScheduledResourceRequestImpl() override {
188 request_->RemoveUserData(kUserDataKey);
189 scheduler_->RemoveRequest(this);
190 }
191
192 void ChangePriority(net::RequestPriority new_priority,
193 int intra_priority_value) override {
194 scheduler_->ReprioritizeRequest(this, new_priority, intra_priority_value);
195 }
196
197 static ScheduledResourceRequest* ForRequest(net::URLRequest* request) {
198 return static_cast<UnownedPointer*>(request->GetUserData(kUserDataKey))
199 ->pointer;
200 }
187 201
188 void Start() { 202 void Start() {
189 ready_ = true; 203 ready_ = true;
190 if (!request_->status().is_success()) 204 if (!request_->status().is_success())
191 return; 205 return;
192 base::TimeTicks time = base::TimeTicks::Now(); 206 base::TimeTicks time = base::TimeTicks::Now();
193 ClientState current_state = scheduler_->GetClientState(client_id_); 207 ClientState current_state = scheduler_->GetClientState(client_id_);
194 // Note: the client state isn't perfectly accurate since it won't capture 208 // Note: the client state isn't perfectly accurate since it won't capture
195 // tabs which have switched between active and background multiple times. 209 // tabs which have switched between active and background multiple times.
196 // Ex: A tab with the following transitions Active -> Background -> Active 210 // Ex: A tab with the following transitions Active -> Background -> Active
(...skipping 22 matching lines...) Expand all
219 233
220 void set_request_priority_params(const RequestPriorityParams& priority) { 234 void set_request_priority_params(const RequestPriorityParams& priority) {
221 priority_ = priority; 235 priority_ = priority;
222 } 236 }
223 const RequestPriorityParams& get_request_priority_params() const { 237 const RequestPriorityParams& get_request_priority_params() const {
224 return priority_; 238 return priority_;
225 } 239 }
226 const ClientId& client_id() const { return client_id_; } 240 const ClientId& client_id() const { return client_id_; }
227 net::URLRequest* url_request() { return request_; } 241 net::URLRequest* url_request() { return request_; }
228 const net::URLRequest* url_request() const { return request_; } 242 const net::URLRequest* url_request() const { return request_; }
243 bool is_async() const { return is_async_; }
229 uint32 fifo_ordering() const { return fifo_ordering_; } 244 uint32 fifo_ordering() const { return fifo_ordering_; }
230 void set_fifo_ordering(uint32 fifo_ordering) { 245 void set_fifo_ordering(uint32 fifo_ordering) {
231 fifo_ordering_ = fifo_ordering; 246 fifo_ordering_ = fifo_ordering;
232 } 247 }
233 RequestClassification classification() const { 248 RequestClassification classification() const {
234 return classification_; 249 return classification_;
235 } 250 }
236 void set_classification(RequestClassification classification) { 251 void set_classification(RequestClassification classification) {
237 classification_ = classification; 252 classification_ = classification;
238 } 253 }
239 254
240 private: 255 private:
241 // ResourceMessageDelegate interface: 256 class UnownedPointer : public base::SupportsUserData::Data {
242 bool OnMessageReceived(const IPC::Message& message) override { 257 public:
243 bool handled = true; 258 UnownedPointer(ScheduledResourceRequestImpl* pointer) : pointer(pointer) {}
mmenke 2015/08/14 15:23:14 explicit
Adam Rice 2015/08/14 17:17:22 Done.
244 IPC_BEGIN_MESSAGE_MAP(ScheduledResourceRequest, message) 259
245 IPC_MESSAGE_HANDLER(ResourceHostMsg_DidChangePriority, DidChangePriority) 260 ScheduledResourceRequestImpl* const pointer;
mmenke 2015/08/14 15:23:15 This should be private, with an accessor, per Goog
Adam Rice 2015/08/14 17:17:23 Done.
246 IPC_MESSAGE_UNHANDLED(handled = false) 261
247 IPC_END_MESSAGE_MAP() 262 private:
248 return handled; 263 DISALLOW_COPY_AND_ASSIGN(UnownedPointer);
249 } 264 };
265
266 static const void* const kUserDataKey;
250 267
251 // ResourceThrottle interface: 268 // ResourceThrottle interface:
252 void WillStartRequest(bool* defer) override { 269 void WillStartRequest(bool* defer) override {
253 deferred_ = *defer = !ready_; 270 deferred_ = *defer = !ready_;
254 time_deferred_ = base::TimeTicks::Now(); 271 time_deferred_ = base::TimeTicks::Now();
255 } 272 }
256 273
257 const char* GetNameForLogging() const override { return "ResourceScheduler"; } 274 const char* GetNameForLogging() const override { return "ResourceScheduler"; }
258 275
259 void DidChangePriority(int request_id, net::RequestPriority new_priority,
260 int intra_priority_value) {
261 scheduler_->ReprioritizeRequest(this, new_priority, intra_priority_value);
262 }
263
264 const ClientId client_id_; 276 const ClientId client_id_;
265 const ResourceScheduler::ClientState client_state_on_creation_; 277 const ResourceScheduler::ClientState client_state_on_creation_;
266 net::URLRequest* request_; 278 net::URLRequest* request_;
267 bool ready_; 279 bool ready_;
268 bool deferred_; 280 bool deferred_;
281 bool is_async_;
269 RequestClassification classification_; 282 RequestClassification classification_;
270 ResourceScheduler* scheduler_; 283 ResourceScheduler* scheduler_;
271 RequestPriorityParams priority_; 284 RequestPriorityParams priority_;
272 uint32 fifo_ordering_; 285 uint32 fifo_ordering_;
273 base::TimeTicks time_deferred_; 286 base::TimeTicks time_deferred_;
274 287
275 DISALLOW_COPY_AND_ASSIGN(ScheduledResourceRequest); 288 DISALLOW_COPY_AND_ASSIGN(ScheduledResourceRequestImpl);
276 }; 289 };
277 290
291 const void* const
292 ResourceScheduler::ScheduledResourceRequestImpl::kUserDataKey =
293 &ResourceScheduler::ScheduledResourceRequestImpl::kUserDataKey;
294
295 ResourceScheduler::ScheduledResourceRequest::ScheduledResourceRequest() {}
296 ResourceScheduler::ScheduledResourceRequest::~ScheduledResourceRequest() {}
297 ResourceScheduler::ScheduledResourceRequest*
298 ResourceScheduler::ScheduledResourceRequest::ForRequest(
299 net::URLRequest* request) {
300 return ResourceScheduler::ScheduledResourceRequestImpl::ForRequest(request);
301 }
mmenke 2015/08/14 15:23:14 nit: believe there should be a blank line between
Adam Rice 2015/08/14 17:17:23 Removed.
302
278 bool ResourceScheduler::ScheduledResourceSorter::operator()( 303 bool ResourceScheduler::ScheduledResourceSorter::operator()(
279 const ScheduledResourceRequest* a, 304 const ScheduledResourceRequestImpl* a,
280 const ScheduledResourceRequest* b) const { 305 const ScheduledResourceRequestImpl* b) const {
281 // Want the set to be ordered first by decreasing priority, then by 306 // Want the set to be ordered first by decreasing priority, then by
282 // decreasing intra_priority. 307 // decreasing intra_priority.
283 // ie. with (priority, intra_priority) 308 // ie. with (priority, intra_priority)
284 // [(1, 0), (1, 0), (0, 100), (0, 0)] 309 // [(1, 0), (1, 0), (0, 100), (0, 0)]
285 if (a->get_request_priority_params() != b->get_request_priority_params()) 310 if (a->get_request_priority_params() != b->get_request_priority_params())
286 return a->get_request_priority_params().GreaterThan( 311 return a->get_request_priority_params().GreaterThan(
287 b->get_request_priority_params()); 312 b->get_request_priority_params());
288 313
289 // If priority/intra_priority is the same, fall back to fifo ordering. 314 // If priority/intra_priority is the same, fall back to fifo ordering.
290 // std::multiset doesn't guarantee this until c++11. 315 // std::multiset doesn't guarantee this until c++11.
291 return a->fifo_ordering() < b->fifo_ordering(); 316 return a->fifo_ordering() < b->fifo_ordering();
292 } 317 }
293 318
294 void ResourceScheduler::RequestQueue::Insert( 319 void ResourceScheduler::RequestQueue::Insert(
295 ScheduledResourceRequest* request) { 320 ScheduledResourceRequestImpl* request) {
296 DCHECK(!ContainsKey(pointers_, request)); 321 DCHECK(!ContainsKey(pointers_, request));
297 request->set_fifo_ordering(MakeFifoOrderingId()); 322 request->set_fifo_ordering(MakeFifoOrderingId());
298 pointers_[request] = queue_.insert(request); 323 pointers_[request] = queue_.insert(request);
299 } 324 }
300 325
301 // Each client represents a tab. 326 // Each client represents a tab.
302 class ResourceScheduler::Client { 327 class ResourceScheduler::Client {
303 public: 328 public:
304 explicit Client(ResourceScheduler* scheduler, 329 explicit Client(ResourceScheduler* scheduler,
305 bool is_visible, 330 bool is_visible,
(...skipping 12 matching lines...) Expand all
318 343
319 ~Client() { 344 ~Client() {
320 // Update to default state and pause to ensure the scheduler has a 345 // Update to default state and pause to ensure the scheduler has a
321 // correct count of relevant types of clients. 346 // correct count of relevant types of clients.
322 is_visible_ = false; 347 is_visible_ = false;
323 is_audible_ = false; 348 is_audible_ = false;
324 is_paused_ = true; 349 is_paused_ = true;
325 UpdateThrottleState(); 350 UpdateThrottleState();
326 } 351 }
327 352
328 void ScheduleRequest( 353 void ScheduleRequest(net::URLRequest* url_request,
329 net::URLRequest* url_request, 354 ScheduledResourceRequestImpl* request) {
330 ScheduledResourceRequest* request) {
331 if (ShouldStartRequest(request) == START_REQUEST) 355 if (ShouldStartRequest(request) == START_REQUEST)
332 StartRequest(request); 356 StartRequest(request);
333 else 357 else
334 pending_requests_.Insert(request); 358 pending_requests_.Insert(request);
335 SetRequestClassification(request, ClassifyRequest(request)); 359 SetRequestClassification(request, ClassifyRequest(request));
336 } 360 }
337 361
338 void RemoveRequest(ScheduledResourceRequest* request) { 362 void RemoveRequest(ScheduledResourceRequestImpl* request) {
339 if (pending_requests_.IsQueued(request)) { 363 if (pending_requests_.IsQueued(request)) {
340 pending_requests_.Erase(request); 364 pending_requests_.Erase(request);
341 DCHECK(!ContainsKey(in_flight_requests_, request)); 365 DCHECK(!ContainsKey(in_flight_requests_, request));
342 } else { 366 } else {
343 EraseInFlightRequest(request); 367 EraseInFlightRequest(request);
344 368
345 // Removing this request may have freed up another to load. 369 // Removing this request may have freed up another to load.
346 LoadAnyStartablePendingRequests(); 370 LoadAnyStartablePendingRequests();
347 } 371 }
348 } 372 }
349 373
350 RequestSet StartAndRemoveAllRequests() { 374 RequestSet StartAndRemoveAllRequests() {
351 // First start any pending requests so that they will be moved into 375 // First start any pending requests so that they will be moved into
352 // in_flight_requests_. This may exceed the limits 376 // in_flight_requests_. This may exceed the limits
353 // kMaxNumDelayableRequestsPerClient, kMaxNumDelayableRequestsPerHost and 377 // kMaxNumDelayableRequestsPerClient, kMaxNumDelayableRequestsPerHost and
354 // kMaxNumThrottledRequestsPerClient, so this method must not do anything 378 // kMaxNumThrottledRequestsPerClient, so this method must not do anything
355 // that depends on those limits before calling ClearInFlightRequests() 379 // that depends on those limits before calling ClearInFlightRequests()
356 // below. 380 // below.
357 while (!pending_requests_.IsEmpty()) { 381 while (!pending_requests_.IsEmpty()) {
358 ScheduledResourceRequest* request = 382 ScheduledResourceRequestImpl* request =
359 *pending_requests_.GetNextHighestIterator(); 383 *pending_requests_.GetNextHighestIterator();
360 pending_requests_.Erase(request); 384 pending_requests_.Erase(request);
361 // StartRequest() may modify pending_requests_. TODO(ricea): Does it? 385 // StartRequest() may modify pending_requests_. TODO(ricea): Does it?
362 StartRequest(request); 386 StartRequest(request);
363 } 387 }
364 RequestSet unowned_requests; 388 RequestSet unowned_requests;
365 for (RequestSet::iterator it = in_flight_requests_.begin(); 389 for (RequestSet::iterator it = in_flight_requests_.begin();
366 it != in_flight_requests_.end(); ++it) { 390 it != in_flight_requests_.end(); ++it) {
367 unowned_requests.insert(*it); 391 unowned_requests.insert(*it);
368 (*it)->set_classification(NORMAL_REQUEST); 392 (*it)->set_classification(NORMAL_REQUEST);
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
479 LoadAnyStartablePendingRequests(); 503 LoadAnyStartablePendingRequests();
480 } 504 }
481 505
482 void OnReceivedSpdyProxiedHttpResponse() { 506 void OnReceivedSpdyProxiedHttpResponse() {
483 if (!using_spdy_proxy_) { 507 if (!using_spdy_proxy_) {
484 using_spdy_proxy_ = true; 508 using_spdy_proxy_ = true;
485 LoadAnyStartablePendingRequests(); 509 LoadAnyStartablePendingRequests();
486 } 510 }
487 } 511 }
488 512
489 void ReprioritizeRequest(ScheduledResourceRequest* request, 513 void ReprioritizeRequest(ScheduledResourceRequestImpl* request,
490 RequestPriorityParams old_priority_params, 514 RequestPriorityParams old_priority_params,
491 RequestPriorityParams new_priority_params) { 515 RequestPriorityParams new_priority_params) {
492 request->url_request()->SetPriority(new_priority_params.priority); 516 request->url_request()->SetPriority(new_priority_params.priority);
493 request->set_request_priority_params(new_priority_params); 517 request->set_request_priority_params(new_priority_params);
494 if (!pending_requests_.IsQueued(request)) { 518 if (!pending_requests_.IsQueued(request)) {
495 DCHECK(ContainsKey(in_flight_requests_, request)); 519 DCHECK(ContainsKey(in_flight_requests_, request));
496 // The priority of the request and priority support of the server may 520 // The priority of the request and priority support of the server may
497 // have changed, so update the delayable count. 521 // have changed, so update the delayable count.
498 SetRequestClassification(request, ClassifyRequest(request)); 522 SetRequestClassification(request, ClassifyRequest(request));
499 // Request has already started. 523 // Request has already started.
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
553 SetThrottleState(COALESCED); 577 SetThrottleState(COALESCED);
554 } 578 }
555 579
556 private: 580 private:
557 enum ShouldStartReqResult { 581 enum ShouldStartReqResult {
558 DO_NOT_START_REQUEST_AND_STOP_SEARCHING, 582 DO_NOT_START_REQUEST_AND_STOP_SEARCHING,
559 DO_NOT_START_REQUEST_AND_KEEP_SEARCHING, 583 DO_NOT_START_REQUEST_AND_KEEP_SEARCHING,
560 START_REQUEST, 584 START_REQUEST,
561 }; 585 };
562 586
563 void InsertInFlightRequest(ScheduledResourceRequest* request) { 587 void InsertInFlightRequest(ScheduledResourceRequestImpl* request) {
564 in_flight_requests_.insert(request); 588 in_flight_requests_.insert(request);
565 SetRequestClassification(request, ClassifyRequest(request)); 589 SetRequestClassification(request, ClassifyRequest(request));
566 } 590 }
567 591
568 void EraseInFlightRequest(ScheduledResourceRequest* request) { 592 void EraseInFlightRequest(ScheduledResourceRequestImpl* request) {
569 size_t erased = in_flight_requests_.erase(request); 593 size_t erased = in_flight_requests_.erase(request);
570 DCHECK_EQ(1u, erased); 594 DCHECK_EQ(1u, erased);
571 // Clear any special state that we were tracking for this request. 595 // Clear any special state that we were tracking for this request.
572 SetRequestClassification(request, NORMAL_REQUEST); 596 SetRequestClassification(request, NORMAL_REQUEST);
573 } 597 }
574 598
575 void ClearInFlightRequests() { 599 void ClearInFlightRequests() {
576 in_flight_requests_.clear(); 600 in_flight_requests_.clear();
577 in_flight_delayable_count_ = 0; 601 in_flight_delayable_count_ = 0;
578 total_layout_blocking_count_ = 0; 602 total_layout_blocking_count_ = 0;
(...skipping 11 matching lines...) Expand all
590 for (RequestQueue::NetQueue::const_iterator 614 for (RequestQueue::NetQueue::const_iterator
591 it = pending_requests_.GetNextHighestIterator(); 615 it = pending_requests_.GetNextHighestIterator();
592 it != pending_requests_.End(); ++it) { 616 it != pending_requests_.End(); ++it) {
593 if ((*it)->classification() == classification) 617 if ((*it)->classification() == classification)
594 classification_request_count++; 618 classification_request_count++;
595 } 619 }
596 } 620 }
597 return classification_request_count; 621 return classification_request_count;
598 } 622 }
599 623
600 void SetRequestClassification(ScheduledResourceRequest* request, 624 void SetRequestClassification(ScheduledResourceRequestImpl* request,
601 RequestClassification classification) { 625 RequestClassification classification) {
602 RequestClassification old_classification = request->classification(); 626 RequestClassification old_classification = request->classification();
603 if (old_classification == classification) 627 if (old_classification == classification)
604 return; 628 return;
605 629
606 if (old_classification == IN_FLIGHT_DELAYABLE_REQUEST) 630 if (old_classification == IN_FLIGHT_DELAYABLE_REQUEST)
607 in_flight_delayable_count_--; 631 in_flight_delayable_count_--;
608 if (old_classification == LAYOUT_BLOCKING_REQUEST) 632 if (old_classification == LAYOUT_BLOCKING_REQUEST)
609 total_layout_blocking_count_--; 633 total_layout_blocking_count_--;
610 634
611 if (classification == IN_FLIGHT_DELAYABLE_REQUEST) 635 if (classification == IN_FLIGHT_DELAYABLE_REQUEST)
612 in_flight_delayable_count_++; 636 in_flight_delayable_count_++;
613 if (classification == LAYOUT_BLOCKING_REQUEST) 637 if (classification == LAYOUT_BLOCKING_REQUEST)
614 total_layout_blocking_count_++; 638 total_layout_blocking_count_++;
615 639
616 request->set_classification(classification); 640 request->set_classification(classification);
617 DCHECK_EQ( 641 DCHECK_EQ(
618 CountRequestsWithClassification(IN_FLIGHT_DELAYABLE_REQUEST, false), 642 CountRequestsWithClassification(IN_FLIGHT_DELAYABLE_REQUEST, false),
619 in_flight_delayable_count_); 643 in_flight_delayable_count_);
620 DCHECK_EQ(CountRequestsWithClassification(LAYOUT_BLOCKING_REQUEST, true), 644 DCHECK_EQ(CountRequestsWithClassification(LAYOUT_BLOCKING_REQUEST, true),
621 total_layout_blocking_count_); 645 total_layout_blocking_count_);
622 } 646 }
623 647
624 RequestClassification ClassifyRequest(ScheduledResourceRequest* request) { 648 RequestClassification ClassifyRequest(ScheduledResourceRequestImpl* request) {
625 // If a request is already marked as layout-blocking make sure to keep the 649 // If a request is already marked as layout-blocking make sure to keep the
626 // classification across redirects unless the priority was lowered. 650 // classification across redirects unless the priority was lowered.
627 if (request->classification() == LAYOUT_BLOCKING_REQUEST && 651 if (request->classification() == LAYOUT_BLOCKING_REQUEST &&
628 request->url_request()->priority() > net::LOW) { 652 request->url_request()->priority() > net::LOW) {
629 return LAYOUT_BLOCKING_REQUEST; 653 return LAYOUT_BLOCKING_REQUEST;
630 } 654 }
631 655
632 if (!has_body_ && request->url_request()->priority() > net::LOW) 656 if (!has_body_ && request->url_request()->priority() > net::LOW)
633 return LAYOUT_BLOCKING_REQUEST; 657 return LAYOUT_BLOCKING_REQUEST;
634 658
(...skipping 19 matching lines...) Expand all
654 net::HostPortPair::FromURL((*it)->url_request()->url()); 678 net::HostPortPair::FromURL((*it)->url_request()->url());
655 if (active_request_host.Equals(host_port_pair)) { 679 if (active_request_host.Equals(host_port_pair)) {
656 same_host_count++; 680 same_host_count++;
657 if (same_host_count >= kMaxNumDelayableRequestsPerHost) 681 if (same_host_count >= kMaxNumDelayableRequestsPerHost)
658 return true; 682 return true;
659 } 683 }
660 } 684 }
661 return false; 685 return false;
662 } 686 }
663 687
664 void StartRequest(ScheduledResourceRequest* request) { 688 void StartRequest(ScheduledResourceRequestImpl* request) {
665 InsertInFlightRequest(request); 689 InsertInFlightRequest(request);
666 request->Start(); 690 request->Start();
667 } 691 }
668 692
669 // ShouldStartRequest is the main scheduling algorithm. 693 // ShouldStartRequest is the main scheduling algorithm.
670 // 694 //
671 // Requests are evaluated on five attributes: 695 // Requests are evaluated on five attributes:
672 // 696 //
673 // 1. Non-delayable requests: 697 // 1. Non-delayable requests:
674 // * Synchronous requests. 698 // * Synchronous requests.
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
712 // * If no high priority requests are in flight, start loading low priority 736 // * If no high priority requests are in flight, start loading low priority
713 // requests. 737 // requests.
714 // 738 //
715 // COALESCED Clients never load requests, with the following exceptions: 739 // COALESCED Clients never load requests, with the following exceptions:
716 // * Non-delayable requests are issued imediately. 740 // * Non-delayable requests are issued imediately.
717 // * On a (currently 5 second) heart beat, they load all requests as an 741 // * On a (currently 5 second) heart beat, they load all requests as an
718 // UNTHROTTLED Client, and then return to the COALESCED state. 742 // UNTHROTTLED Client, and then return to the COALESCED state.
719 // * When an active Client makes a request, they are THROTTLED until the 743 // * When an active Client makes a request, they are THROTTLED until the
720 // active Client finishes loading. 744 // active Client finishes loading.
721 ShouldStartReqResult ShouldStartRequest( 745 ShouldStartReqResult ShouldStartRequest(
722 ScheduledResourceRequest* request) const { 746 ScheduledResourceRequestImpl* request) const {
723 const net::URLRequest& url_request = *request->url_request(); 747 const net::URLRequest& url_request = *request->url_request();
724 // Syncronous requests could block the entire render, which could impact 748 // Syncronous requests could block the entire render, which could impact
725 // user-observable Clients. 749 // user-observable Clients.
726 if (!ResourceRequestInfo::ForRequest(&url_request)->IsAsync()) { 750 if (!request->is_async()) {
727 return START_REQUEST; 751 return START_REQUEST;
728 } 752 }
729 753
730 // TODO(simonjam): This may end up causing disk contention. We should 754 // TODO(simonjam): This may end up causing disk contention. We should
731 // experiment with throttling if that happens. 755 // experiment with throttling if that happens.
732 // TODO(aiolos): We probably want to Coalesce these as well to avoid 756 // TODO(aiolos): We probably want to Coalesce these as well to avoid
733 // waking the disk. 757 // waking the disk.
734 if (!url_request.url().SchemeIsHTTPOrHTTPS()) { 758 if (!url_request.url().SchemeIsHTTPOrHTTPS()) {
735 return START_REQUEST; 759 return START_REQUEST;
736 } 760 }
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
803 // 1) We start the request, remove it from the list, and keep checking. 827 // 1) We start the request, remove it from the list, and keep checking.
804 // 2) We do NOT start the request, but ShouldStartRequest() signals us that 828 // 2) We do NOT start the request, but ShouldStartRequest() signals us that
805 // there may be room for other requests, so we keep checking and leave 829 // there may be room for other requests, so we keep checking and leave
806 // the previous request still in the list. 830 // the previous request still in the list.
807 // 3) We do not start the request, same as above, but StartRequest() tells 831 // 3) We do not start the request, same as above, but StartRequest() tells
808 // us there's no point in checking any further requests. 832 // us there's no point in checking any further requests.
809 RequestQueue::NetQueue::iterator request_iter = 833 RequestQueue::NetQueue::iterator request_iter =
810 pending_requests_.GetNextHighestIterator(); 834 pending_requests_.GetNextHighestIterator();
811 835
812 while (request_iter != pending_requests_.End()) { 836 while (request_iter != pending_requests_.End()) {
813 ScheduledResourceRequest* request = *request_iter; 837 ScheduledResourceRequestImpl* request = *request_iter;
814 ShouldStartReqResult query_result = ShouldStartRequest(request); 838 ShouldStartReqResult query_result = ShouldStartRequest(request);
815 839
816 if (query_result == START_REQUEST) { 840 if (query_result == START_REQUEST) {
817 pending_requests_.Erase(request); 841 pending_requests_.Erase(request);
818 StartRequest(request); 842 StartRequest(request);
819 843
820 // StartRequest can modify the pending list, so we (re)start evaluation 844 // StartRequest can modify the pending list, so we (re)start evaluation
821 // from the currently highest priority request. Avoid copying a singular 845 // from the currently highest priority request. Avoid copying a singular
822 // iterator, which would trigger undefined behavior. 846 // iterator, which would trigger undefined behavior.
823 if (pending_requests_.GetNextHighestIterator() == 847 if (pending_requests_.GetNextHighestIterator() ==
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
898 OnLoadingActiveClientsStateChangedForAllClients(); 922 OnLoadingActiveClientsStateChangedForAllClients();
899 } 923 }
900 924
901 ResourceScheduler::ClientThrottleState 925 ResourceScheduler::ClientThrottleState
902 ResourceScheduler::GetClientStateForTesting(int child_id, int route_id) { 926 ResourceScheduler::GetClientStateForTesting(int child_id, int route_id) {
903 Client* client = GetClient(child_id, route_id); 927 Client* client = GetClient(child_id, route_id);
904 DCHECK(client); 928 DCHECK(client);
905 return client->throttle_state(); 929 return client->throttle_state();
906 } 930 }
907 931
908 scoped_ptr<ResourceThrottle> ResourceScheduler::ScheduleRequest( 932 scoped_ptr<ResourceScheduler::ScheduledResourceRequest>
909 int child_id, 933 ResourceScheduler::ScheduleRequest(int child_id,
910 int route_id, 934 int route_id,
911 net::URLRequest* url_request) { 935 bool is_async,
936 net::URLRequest* url_request) {
912 DCHECK(CalledOnValidThread()); 937 DCHECK(CalledOnValidThread());
913 ClientId client_id = MakeClientId(child_id, route_id); 938 ClientId client_id = MakeClientId(child_id, route_id);
914 scoped_ptr<ScheduledResourceRequest> request(new ScheduledResourceRequest( 939 scoped_ptr<ScheduledResourceRequestImpl> request(
915 client_id, 940 new ScheduledResourceRequestImpl(
916 url_request, 941 client_id, url_request, this,
917 this, 942 RequestPriorityParams(url_request->priority(), 0), is_async));
918 RequestPriorityParams(url_request->priority(), 0)));
919 943
920 ClientMap::iterator it = client_map_.find(client_id); 944 ClientMap::iterator it = client_map_.find(client_id);
921 if (it == client_map_.end()) { 945 if (it == client_map_.end()) {
922 // There are several ways this could happen: 946 // There are several ways this could happen:
923 // 1. <a ping> requests don't have a route_id. 947 // 1. <a ping> requests don't have a route_id.
924 // 2. Most unittests don't send the IPCs needed to register Clients. 948 // 2. Most unittests don't send the IPCs needed to register Clients.
925 // 3. The tab is closed while a RequestResource IPC is in flight. 949 // 3. The tab is closed while a RequestResource IPC is in flight.
926 unowned_requests_.insert(request.get()); 950 unowned_requests_.insert(request.get());
927 request->Start(); 951 request->Start();
928 return request.Pass(); 952 return request.Pass();
929 } 953 }
930 954
931 Client* client = it->second; 955 Client* client = it->second;
932 client->ScheduleRequest(url_request, request.get()); 956 client->ScheduleRequest(url_request, request.get());
933 return request.Pass(); 957 return request.Pass();
934 } 958 }
935 959
936 void ResourceScheduler::RemoveRequest(ScheduledResourceRequest* request) { 960 void ResourceScheduler::RemoveRequest(ScheduledResourceRequestImpl* request) {
937 DCHECK(CalledOnValidThread()); 961 DCHECK(CalledOnValidThread());
938 if (ContainsKey(unowned_requests_, request)) { 962 if (ContainsKey(unowned_requests_, request)) {
939 unowned_requests_.erase(request); 963 unowned_requests_.erase(request);
940 return; 964 return;
941 } 965 }
942 966
943 ClientMap::iterator client_it = client_map_.find(request->client_id()); 967 ClientMap::iterator client_it = client_map_.find(request->client_id());
944 if (client_it == client_map_.end()) { 968 if (client_it == client_map_.end()) {
945 return; 969 return;
946 } 970 }
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after
1164 } 1188 }
1165 1189
1166 ResourceScheduler::ClientState ResourceScheduler::GetClientState( 1190 ResourceScheduler::ClientState ResourceScheduler::GetClientState(
1167 ClientId client_id) const { 1191 ClientId client_id) const {
1168 ClientMap::const_iterator client_it = client_map_.find(client_id); 1192 ClientMap::const_iterator client_it = client_map_.find(client_id);
1169 if (client_it == client_map_.end()) 1193 if (client_it == client_map_.end())
1170 return UNKNOWN; 1194 return UNKNOWN;
1171 return client_it->second->is_active() ? ACTIVE : BACKGROUND; 1195 return client_it->second->is_active() ? ACTIVE : BACKGROUND;
1172 } 1196 }
1173 1197
1174 void ResourceScheduler::ReprioritizeRequest(ScheduledResourceRequest* request, 1198 void ResourceScheduler::ReprioritizeRequest(
1175 net::RequestPriority new_priority, 1199 ScheduledResourceRequestImpl* request,
1176 int new_intra_priority_value) { 1200 net::RequestPriority new_priority,
1201 int new_intra_priority_value) {
mmenke 2015/08/14 15:23:14 Why not have the RDH call this method with the URL
Adam Rice 2015/08/14 17:17:22 Oh. Thank you. Done.
1177 if (request->url_request()->load_flags() & net::LOAD_IGNORE_LIMITS) { 1202 if (request->url_request()->load_flags() & net::LOAD_IGNORE_LIMITS) {
1178 // We should not be re-prioritizing requests with the 1203 // We should not be re-prioritizing requests with the
1179 // IGNORE_LIMITS flag. 1204 // IGNORE_LIMITS flag.
1180 NOTREACHED(); 1205 NOTREACHED();
1181 return; 1206 return;
1182 } 1207 }
1183 RequestPriorityParams new_priority_params(new_priority, 1208 RequestPriorityParams new_priority_params(new_priority,
1184 new_intra_priority_value); 1209 new_intra_priority_value);
1185 RequestPriorityParams old_priority_params = 1210 RequestPriorityParams old_priority_params =
1186 request->get_request_priority_params(); 1211 request->get_request_priority_params();
(...skipping 15 matching lines...) Expand all
1202 client->ReprioritizeRequest( 1227 client->ReprioritizeRequest(
1203 request, old_priority_params, new_priority_params); 1228 request, old_priority_params, new_priority_params);
1204 } 1229 }
1205 1230
1206 ResourceScheduler::ClientId ResourceScheduler::MakeClientId( 1231 ResourceScheduler::ClientId ResourceScheduler::MakeClientId(
1207 int child_id, int route_id) { 1232 int child_id, int route_id) {
1208 return (static_cast<ResourceScheduler::ClientId>(child_id) << 32) | route_id; 1233 return (static_cast<ResourceScheduler::ClientId>(child_id) << 32) | route_id;
1209 } 1234 }
1210 1235
1211 } // namespace content 1236 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/loader/resource_scheduler.h ('k') | content/browser/loader/resource_scheduler_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698