OLD | NEW |
---|---|
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/stl_util.h" | 9 #include "base/stl_util.h" |
10 #include "content/common/resource_messages.h" | 10 #include "content/common/resource_messages.h" |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
121 ResourceScheduler* scheduler, | 121 ResourceScheduler* scheduler, |
122 const RequestPriorityParams& priority) | 122 const RequestPriorityParams& priority) |
123 : ResourceMessageDelegate(request), | 123 : ResourceMessageDelegate(request), |
124 client_id_(client_id), | 124 client_id_(client_id), |
125 request_(request), | 125 request_(request), |
126 ready_(false), | 126 ready_(false), |
127 deferred_(false), | 127 deferred_(false), |
128 scheduler_(scheduler), | 128 scheduler_(scheduler), |
129 priority_(priority), | 129 priority_(priority), |
130 fifo_ordering_(0), | 130 fifo_ordering_(0), |
131 accounted_as_delayable_request_(false) { | 131 classification_(NORMAL_REQUEST) { |
132 TRACE_EVENT_ASYNC_BEGIN1("net", "URLRequest", request_, | 132 TRACE_EVENT_ASYNC_BEGIN1("net", "URLRequest", request_, |
133 "url", request->url().spec()); | 133 "url", request->url().spec()); |
134 } | 134 } |
135 | 135 |
136 virtual ~ScheduledResourceRequest() { | 136 virtual ~ScheduledResourceRequest() { |
137 scheduler_->RemoveRequest(this); | 137 scheduler_->RemoveRequest(this); |
138 } | 138 } |
139 | 139 |
140 void Start() { | 140 void Start() { |
141 TRACE_EVENT_ASYNC_STEP_PAST0("net", "URLRequest", request_, "Queued"); | 141 TRACE_EVENT_ASYNC_STEP_PAST0("net", "URLRequest", request_, "Queued"); |
(...skipping 10 matching lines...) Expand all Loading... | |
152 const RequestPriorityParams& get_request_priority_params() const { | 152 const RequestPriorityParams& get_request_priority_params() const { |
153 return priority_; | 153 return priority_; |
154 } | 154 } |
155 const ClientId& client_id() const { return client_id_; } | 155 const ClientId& client_id() const { return client_id_; } |
156 net::URLRequest* url_request() { return request_; } | 156 net::URLRequest* url_request() { return request_; } |
157 const net::URLRequest* url_request() const { return request_; } | 157 const net::URLRequest* url_request() const { return request_; } |
158 uint32 fifo_ordering() const { return fifo_ordering_; } | 158 uint32 fifo_ordering() const { return fifo_ordering_; } |
159 void set_fifo_ordering(uint32 fifo_ordering) { | 159 void set_fifo_ordering(uint32 fifo_ordering) { |
160 fifo_ordering_ = fifo_ordering; | 160 fifo_ordering_ = fifo_ordering; |
161 } | 161 } |
162 bool accounted_as_delayable_request() const { | 162 RequestClassification classification() const { |
163 return accounted_as_delayable_request_; | 163 return classification_; |
164 } | 164 } |
165 void set_accounted_as_delayable_request(bool accounted) { | 165 void set_classification(RequestClassification classification) { |
166 accounted_as_delayable_request_ = accounted; | 166 classification_ = classification; |
167 } | 167 } |
168 | 168 |
169 private: | 169 private: |
170 // ResourceMessageDelegate interface: | 170 // ResourceMessageDelegate interface: |
171 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE { | 171 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE { |
172 bool handled = true; | 172 bool handled = true; |
173 IPC_BEGIN_MESSAGE_MAP(ScheduledResourceRequest, message) | 173 IPC_BEGIN_MESSAGE_MAP(ScheduledResourceRequest, message) |
174 IPC_MESSAGE_HANDLER(ResourceHostMsg_DidChangePriority, DidChangePriority) | 174 IPC_MESSAGE_HANDLER(ResourceHostMsg_DidChangePriority, DidChangePriority) |
175 IPC_MESSAGE_UNHANDLED(handled = false) | 175 IPC_MESSAGE_UNHANDLED(handled = false) |
176 IPC_END_MESSAGE_MAP() | 176 IPC_END_MESSAGE_MAP() |
(...skipping 11 matching lines...) Expand all Loading... | |
188 | 188 |
189 void DidChangePriority(int request_id, net::RequestPriority new_priority, | 189 void DidChangePriority(int request_id, net::RequestPriority new_priority, |
190 int intra_priority_value) { | 190 int intra_priority_value) { |
191 scheduler_->ReprioritizeRequest(this, new_priority, intra_priority_value); | 191 scheduler_->ReprioritizeRequest(this, new_priority, intra_priority_value); |
192 } | 192 } |
193 | 193 |
194 ClientId client_id_; | 194 ClientId client_id_; |
195 net::URLRequest* request_; | 195 net::URLRequest* request_; |
196 bool ready_; | 196 bool ready_; |
197 bool deferred_; | 197 bool deferred_; |
198 RequestClassification classification_; | |
198 ResourceScheduler* scheduler_; | 199 ResourceScheduler* scheduler_; |
199 RequestPriorityParams priority_; | 200 RequestPriorityParams priority_; |
200 uint32 fifo_ordering_; | 201 uint32 fifo_ordering_; |
201 // True if the request is delayable in |in_flight_requests_|. | |
202 bool accounted_as_delayable_request_; | |
203 | 202 |
204 DISALLOW_COPY_AND_ASSIGN(ScheduledResourceRequest); | 203 DISALLOW_COPY_AND_ASSIGN(ScheduledResourceRequest); |
205 }; | 204 }; |
206 | 205 |
207 bool ResourceScheduler::ScheduledResourceSorter::operator()( | 206 bool ResourceScheduler::ScheduledResourceSorter::operator()( |
208 const ScheduledResourceRequest* a, | 207 const ScheduledResourceRequest* a, |
209 const ScheduledResourceRequest* b) const { | 208 const ScheduledResourceRequest* b) const { |
210 // Want the set to be ordered first by decreasing priority, then by | 209 // Want the set to be ordered first by decreasing priority, then by |
211 // decreasing intra_priority. | 210 // decreasing intra_priority. |
212 // ie. with (priority, intra_priority) | 211 // ie. with (priority, intra_priority) |
(...skipping 17 matching lines...) Expand all Loading... | |
230 // Each client represents a tab. | 229 // Each client represents a tab. |
231 class ResourceScheduler::Client { | 230 class ResourceScheduler::Client { |
232 public: | 231 public: |
233 explicit Client(ResourceScheduler* scheduler) | 232 explicit Client(ResourceScheduler* scheduler) |
234 : is_audible_(false), | 233 : is_audible_(false), |
235 is_visible_(false), | 234 is_visible_(false), |
236 is_loaded_(false), | 235 is_loaded_(false), |
237 is_paused_(false), | 236 is_paused_(false), |
238 has_body_(false), | 237 has_body_(false), |
239 using_spdy_proxy_(false), | 238 using_spdy_proxy_(false), |
240 total_delayable_count_(0), | 239 in_flight_delayable_count_(0), |
240 total_layout_blocking_count_(0), | |
241 throttle_state_(ResourceScheduler::THROTTLED) { | 241 throttle_state_(ResourceScheduler::THROTTLED) { |
242 scheduler_ = scheduler; | 242 scheduler_ = scheduler; |
243 } | 243 } |
244 | 244 |
245 ~Client() { | 245 ~Client() { |
246 // Update to default state and pause to ensure the scheduler has a | 246 // Update to default state and pause to ensure the scheduler has a |
247 // correct count of relevant types of clients. | 247 // correct count of relevant types of clients. |
248 is_visible_ = false; | 248 is_visible_ = false; |
249 is_audible_ = false; | 249 is_audible_ = false; |
250 is_paused_ = true; | 250 is_paused_ = true; |
251 UpdateThrottleState(); | 251 UpdateThrottleState(); |
252 } | 252 } |
253 | 253 |
254 void ScheduleRequest( | 254 void ScheduleRequest( |
255 net::URLRequest* url_request, | 255 net::URLRequest* url_request, |
256 ScheduledResourceRequest* request) { | 256 ScheduledResourceRequest* request) { |
257 if (ShouldStartRequest(request) == START_REQUEST) { | 257 if (ShouldStartRequest(request) == START_REQUEST) |
258 StartRequest(request); | 258 StartRequest(request); |
259 } else { | 259 else |
260 pending_requests_.Insert(request); | 260 pending_requests_.Insert(request); |
261 } | 261 SetRequestClassification(request, GetRequestClassification(request)); |
262 } | 262 } |
263 | 263 |
264 void RemoveRequest(ScheduledResourceRequest* request) { | 264 void RemoveRequest(ScheduledResourceRequest* request) { |
265 if (pending_requests_.IsQueued(request)) { | 265 if (pending_requests_.IsQueued(request)) { |
266 pending_requests_.Erase(request); | 266 pending_requests_.Erase(request); |
267 DCHECK(!ContainsKey(in_flight_requests_, request)); | 267 DCHECK(!ContainsKey(in_flight_requests_, request)); |
268 } else { | 268 } else { |
269 EraseInFlightRequest(request); | 269 EraseInFlightRequest(request); |
270 | 270 |
271 // Removing this request may have freed up another to load. | 271 // Removing this request may have freed up another to load. |
272 LoadAnyStartablePendingRequests(); | 272 LoadAnyStartablePendingRequests(); |
273 } | 273 } |
274 } | 274 } |
275 | 275 |
276 RequestSet RemoveAllRequests() { | 276 RequestSet RemoveAllRequests() { |
277 RequestSet unowned_requests; | 277 RequestSet unowned_requests; |
278 for (RequestSet::iterator it = in_flight_requests_.begin(); | 278 for (RequestSet::iterator it = in_flight_requests_.begin(); |
279 it != in_flight_requests_.end(); ++it) { | 279 it != in_flight_requests_.end(); ++it) { |
280 unowned_requests.insert(*it); | 280 unowned_requests.insert(*it); |
281 (*it)->set_accounted_as_delayable_request(false); | 281 (*it)->set_classification(NORMAL_REQUEST); |
282 } | 282 } |
283 ClearInFlightRequests(); | 283 ClearInFlightRequests(); |
284 return unowned_requests; | 284 return unowned_requests; |
285 } | 285 } |
286 | 286 |
287 bool is_active() const { return is_visible_ || is_audible_; } | 287 bool is_active() const { return is_visible_ || is_audible_; } |
288 | 288 |
289 bool is_loaded() const { return is_loaded_; } | 289 bool is_loaded() const { return is_loaded_; } |
290 | 290 |
291 void OnAudibilityChanged(bool is_audible) { | 291 void OnAudibilityChanged(bool is_audible) { |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
367 | 367 |
368 void ReprioritizeRequest(ScheduledResourceRequest* request, | 368 void ReprioritizeRequest(ScheduledResourceRequest* request, |
369 RequestPriorityParams old_priority_params, | 369 RequestPriorityParams old_priority_params, |
370 RequestPriorityParams new_priority_params) { | 370 RequestPriorityParams new_priority_params) { |
371 request->url_request()->SetPriority(new_priority_params.priority); | 371 request->url_request()->SetPriority(new_priority_params.priority); |
372 request->set_request_priority_params(new_priority_params); | 372 request->set_request_priority_params(new_priority_params); |
373 if (!pending_requests_.IsQueued(request)) { | 373 if (!pending_requests_.IsQueued(request)) { |
374 DCHECK(ContainsKey(in_flight_requests_, request)); | 374 DCHECK(ContainsKey(in_flight_requests_, request)); |
375 // The priority and SPDY support may have changed, so update the | 375 // The priority and SPDY support may have changed, so update the |
376 // delayable count. | 376 // delayable count. |
377 SetRequestDelayable(request, IsDelayableRequest(request)); | 377 SetRequestClassification(request, GetRequestClassification(request)); |
378 // Request has already started. | 378 // Request has already started. |
379 return; | 379 return; |
380 } | 380 } |
381 | 381 |
382 pending_requests_.Erase(request); | 382 pending_requests_.Erase(request); |
383 pending_requests_.Insert(request); | 383 pending_requests_.Insert(request); |
384 | 384 |
385 if (new_priority_params.priority > old_priority_params.priority) { | 385 if (new_priority_params.priority > old_priority_params.priority) { |
386 // Check if this request is now able to load at its new priority. | 386 // Check if this request is now able to load at its new priority. |
387 LoadAnyStartablePendingRequests(); | 387 LoadAnyStartablePendingRequests(); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
434 | 434 |
435 private: | 435 private: |
436 enum ShouldStartReqResult { | 436 enum ShouldStartReqResult { |
437 DO_NOT_START_REQUEST_AND_STOP_SEARCHING, | 437 DO_NOT_START_REQUEST_AND_STOP_SEARCHING, |
438 DO_NOT_START_REQUEST_AND_KEEP_SEARCHING, | 438 DO_NOT_START_REQUEST_AND_KEEP_SEARCHING, |
439 START_REQUEST, | 439 START_REQUEST, |
440 }; | 440 }; |
441 | 441 |
442 void InsertInFlightRequest(ScheduledResourceRequest* request) { | 442 void InsertInFlightRequest(ScheduledResourceRequest* request) { |
443 in_flight_requests_.insert(request); | 443 in_flight_requests_.insert(request); |
444 if (IsDelayableRequest(request)) | 444 SetRequestClassification(request, GetRequestClassification(request)); |
445 SetRequestDelayable(request, true); | |
446 } | 445 } |
447 | 446 |
448 void EraseInFlightRequest(ScheduledResourceRequest* request) { | 447 void EraseInFlightRequest(ScheduledResourceRequest* request) { |
449 size_t erased = in_flight_requests_.erase(request); | 448 size_t erased = in_flight_requests_.erase(request); |
450 DCHECK_EQ(1u, erased); | 449 DCHECK_EQ(1u, erased); |
451 SetRequestDelayable(request, false); | 450 // Clear any special state that we were tracking for this request. |
452 DCHECK_LE(total_delayable_count_, in_flight_requests_.size()); | 451 SetRequestClassification(request, NORMAL_REQUEST); |
453 } | 452 } |
454 | 453 |
455 void ClearInFlightRequests() { | 454 void ClearInFlightRequests() { |
456 in_flight_requests_.clear(); | 455 in_flight_requests_.clear(); |
457 total_delayable_count_ = 0; | 456 in_flight_delayable_count_ = 0; |
457 total_layout_blocking_count_ = 0; | |
458 } | 458 } |
459 | 459 |
460 bool IsDelayableRequest(ScheduledResourceRequest* request) { | 460 size_t CountRequestsWithClassification( |
461 const RequestClassification classification, const bool include_pending) { | |
462 size_t classification_request_count = 0; | |
463 for (RequestSet::const_iterator it = in_flight_requests_.begin(); | |
464 it != in_flight_requests_.end(); ++it) { | |
465 if ((*it)->classification() == classification) | |
466 classification_request_count++; | |
467 } | |
468 if (include_pending) { | |
469 for (RequestQueue::NetQueue::const_iterator | |
470 it = pending_requests_.GetNextHighestIterator(); | |
471 it != pending_requests_.End(); ++it) { | |
472 if ((*it)->classification() == classification) | |
473 classification_request_count++; | |
474 } | |
475 } | |
476 return classification_request_count; | |
477 } | |
478 | |
479 void SetRequestClassification(ScheduledResourceRequest* request, | |
480 RequestClassification classification) { | |
481 RequestClassification old_classification = request->classification(); | |
482 if (old_classification == classification) | |
483 return; | |
484 | |
485 bool in_flight = !pending_requests_.IsQueued(request); | |
mmenke
2014/08/18 20:59:43
This isn't used.
Pat Meenan
2014/08/20 14:57:31
Done.
| |
486 | |
487 if (old_classification == IN_FLIGHT_DELAYABLE_REQUEST) | |
488 in_flight_delayable_count_--; | |
489 if (old_classification == LAYOUT_BLOCKING_REQUEST) | |
490 total_layout_blocking_count_--; | |
491 | |
492 if (classification == IN_FLIGHT_DELAYABLE_REQUEST) | |
493 in_flight_delayable_count_++; | |
494 if (classification == LAYOUT_BLOCKING_REQUEST) | |
495 total_layout_blocking_count_++; | |
496 | |
497 request->set_classification(classification); | |
498 DCHECK_EQ( | |
499 CountRequestsWithClassification(IN_FLIGHT_DELAYABLE_REQUEST, false), | |
500 in_flight_delayable_count_); | |
501 DCHECK_EQ(CountRequestsWithClassification(LAYOUT_BLOCKING_REQUEST, true), | |
502 total_layout_blocking_count_); | |
503 } | |
504 | |
505 RequestClassification GetRequestClassification( | |
mmenke
2014/08/18 20:59:43
Still think we should reconsider this name, to mak
Pat Meenan
2014/08/20 14:57:32
Done. Changed it to ClassifyRequest() which better
| |
506 ScheduledResourceRequest* request) { | |
507 // If a request is already marked as layout-blocking make sure to keep the | |
508 // classification across redirects unless the priority was lowered. | |
509 if (request->classification() == LAYOUT_BLOCKING_REQUEST && | |
510 request->url_request()->priority() >= net::LOW) { | |
511 return LAYOUT_BLOCKING_REQUEST; | |
512 } | |
513 | |
514 if (!has_body_ && request->url_request()->priority() >= net::LOW) | |
515 return LAYOUT_BLOCKING_REQUEST; | |
516 | |
461 if (request->url_request()->priority() < net::LOW) { | 517 if (request->url_request()->priority() < net::LOW) { |
462 net::HostPortPair host_port_pair = | 518 net::HostPortPair host_port_pair = |
463 net::HostPortPair::FromURL(request->url_request()->url()); | 519 net::HostPortPair::FromURL(request->url_request()->url()); |
464 net::HttpServerProperties& http_server_properties = | 520 net::HttpServerProperties& http_server_properties = |
465 *request->url_request()->context()->http_server_properties(); | 521 *request->url_request()->context()->http_server_properties(); |
466 if (!http_server_properties.SupportsSpdy(host_port_pair)) { | 522 if (!http_server_properties.SupportsSpdy(host_port_pair) && |
467 return true; | 523 !pending_requests_.IsQueued(request)) { |
mmenke
2014/08/18 20:59:42
Can we check in_flight_requests_ instead? Seems w
Pat Meenan
2014/08/20 14:57:32
Done.
| |
524 return IN_FLIGHT_DELAYABLE_REQUEST; | |
468 } | 525 } |
469 } | 526 } |
470 return false; | 527 return NORMAL_REQUEST; |
471 } | |
472 | |
473 void SetRequestDelayable(ScheduledResourceRequest* request, | |
474 bool delayable) { | |
475 if (request->accounted_as_delayable_request() == delayable) | |
476 return; | |
477 if (delayable) | |
478 total_delayable_count_++; | |
479 else | |
480 total_delayable_count_--; | |
481 request->set_accounted_as_delayable_request(delayable); | |
482 } | 528 } |
483 | 529 |
484 bool ShouldKeepSearching( | 530 bool ShouldKeepSearching( |
485 const net::HostPortPair& active_request_host) const { | 531 const net::HostPortPair& active_request_host) const { |
486 size_t same_host_count = 0; | 532 size_t same_host_count = 0; |
487 for (RequestSet::const_iterator it = in_flight_requests_.begin(); | 533 for (RequestSet::const_iterator it = in_flight_requests_.begin(); |
488 it != in_flight_requests_.end(); ++it) { | 534 it != in_flight_requests_.end(); ++it) { |
489 net::HostPortPair host_port_pair = | 535 net::HostPortPair host_port_pair = |
490 net::HostPortPair::FromURL((*it)->url_request()->url()); | 536 net::HostPortPair::FromURL((*it)->url_request()->url()); |
491 if (active_request_host.Equals(host_port_pair)) { | 537 if (active_request_host.Equals(host_port_pair)) { |
492 same_host_count++; | 538 same_host_count++; |
493 if (same_host_count >= kMaxNumDelayableRequestsPerHost) | 539 if (same_host_count >= kMaxNumDelayableRequestsPerHost) |
494 return true; | 540 return true; |
495 } | 541 } |
496 } | 542 } |
497 return false; | 543 return false; |
498 } | 544 } |
499 | 545 |
500 void StartRequest(ScheduledResourceRequest* request) { | 546 void StartRequest(ScheduledResourceRequest* request) { |
501 InsertInFlightRequest(request); | 547 InsertInFlightRequest(request); |
502 request->Start(); | 548 request->Start(); |
503 } | 549 } |
504 | 550 |
505 // ShouldStartRequest is the main scheduling algorithm. | 551 // ShouldStartRequest is the main scheduling algorithm. |
506 // | 552 // |
507 // Requests are categorized into three categories: | 553 // Requests are evaluated on five attributes: |
508 // | 554 // |
509 // 1. Non-delayable requests: | 555 // 1. Non-delayable requests: |
510 // * Synchronous requests. | 556 // * Synchronous requests. |
511 // * Non-HTTP[S] requests. | 557 // * Non-HTTP[S] requests. |
512 // | 558 // |
513 // 2. Requests to SPDY-capable origin servers. | 559 // 2. Requests to SPDY-capable origin servers. |
514 // | 560 // |
515 // 3. High-priority requests: | 561 // 3. High-priority requests: |
516 // * Higher priority requests (>= net::LOW). | 562 // * Higher priority requests (>= net::LOW). |
517 // | 563 // |
518 // 4. Low priority requests | 564 // 4. Layout-blocking requests: |
565 // * High-priority requests initiated before the renderer has a <body>. | |
566 // | |
567 // 5. Low priority requests | |
519 // | 568 // |
520 // The following rules are followed: | 569 // The following rules are followed: |
521 // | 570 // |
522 // ACTIVE_AND_LOADING and UNTHROTTLED Clients follow these rules: | 571 // ACTIVE_AND_LOADING and UNTHROTTLED Clients follow these rules: |
523 // * Non-delayable, High-priority and SDPY capable requests are issued | 572 // * Non-delayable, High-priority and SPDY capable requests are issued |
524 // immediately | 573 // immediately. |
525 // * If no high priority requests are in flight, start loading low priority | |
526 // requests. | |
527 // * Low priority requests are delayable. | 574 // * Low priority requests are delayable. |
528 // * Once the renderer has a <body>, start loading delayable requests. | 575 // * Allow one delayable request to load at a time while layout-blocking |
576 // requests are loading. | |
577 // * If no high priority or layout-blocking requests are in flight, start | |
578 // loading delayable requests. | |
529 // * Never exceed 10 delayable requests in flight per client. | 579 // * Never exceed 10 delayable requests in flight per client. |
530 // * Never exceed 6 delayable requests for a given host. | 580 // * Never exceed 6 delayable requests for a given host. |
531 // * Prior to <body>, allow one delayable request to load at a time. | |
532 // | 581 // |
533 // THROTTLED Clients follow these rules: | 582 // THROTTLED Clients follow these rules: |
534 // * Non-delayable and SPDY-capable requests are issued immediately. | 583 // * Non-delayable and SPDY-capable requests are issued immediately. |
535 // * At most one non-SPDY request will be issued per THROTTLED Client | 584 // * At most one non-SPDY request will be issued per THROTTLED Client |
536 // * If no high priority requests are in flight, start loading low priority | 585 // * If no high priority requests are in flight, start loading low priority |
537 // requests. | 586 // requests. |
538 // | 587 // |
539 // COALESCED Clients never load requests, with the following exceptions: | 588 // COALESCED Clients never load requests, with the following exceptions: |
540 // * Non-delayable requests are issued imediately. | 589 // * Non-delayable requests are issued imediately. |
541 // * On a (currently 5 second) heart beat, they load all requests as an | 590 // * On a (currently 5 second) heart beat, they load all requests as an |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
578 if (http_server_properties.SupportsSpdy(host_port_pair)) { | 627 if (http_server_properties.SupportsSpdy(host_port_pair)) { |
579 return START_REQUEST; | 628 return START_REQUEST; |
580 } | 629 } |
581 | 630 |
582 if (throttle_state_ == THROTTLED && | 631 if (throttle_state_ == THROTTLED && |
583 in_flight_requests_.size() >= kMaxNumThrottledRequestsPerClient) { | 632 in_flight_requests_.size() >= kMaxNumThrottledRequestsPerClient) { |
584 // There may still be SPDY-capable requests that should be issued. | 633 // There may still be SPDY-capable requests that should be issued. |
585 return DO_NOT_START_REQUEST_AND_KEEP_SEARCHING; | 634 return DO_NOT_START_REQUEST_AND_KEEP_SEARCHING; |
586 } | 635 } |
587 | 636 |
637 // High-priority and layout-blocking requests. | |
588 if (url_request.priority() >= net::LOW) { | 638 if (url_request.priority() >= net::LOW) { |
589 return START_REQUEST; | 639 return START_REQUEST; |
590 } | 640 } |
591 | 641 |
592 size_t num_delayable_requests_in_flight = total_delayable_count_; | 642 if (in_flight_delayable_count_ >= kMaxNumDelayableRequestsPerClient) { |
593 if (num_delayable_requests_in_flight >= kMaxNumDelayableRequestsPerClient) { | |
594 return DO_NOT_START_REQUEST_AND_STOP_SEARCHING; | 643 return DO_NOT_START_REQUEST_AND_STOP_SEARCHING; |
595 } | 644 } |
596 | 645 |
597 if (ShouldKeepSearching(host_port_pair)) { | 646 if (ShouldKeepSearching(host_port_pair)) { |
598 // There may be other requests for other hosts we'd allow, | 647 // There may be other requests for other hosts we'd allow, |
599 // so keep checking. | 648 // so keep checking. |
600 return DO_NOT_START_REQUEST_AND_KEEP_SEARCHING; | 649 return DO_NOT_START_REQUEST_AND_KEEP_SEARCHING; |
601 } | 650 } |
602 | 651 |
603 bool have_immediate_requests_in_flight = | 652 bool have_immediate_requests_in_flight = |
604 in_flight_requests_.size() > num_delayable_requests_in_flight; | 653 in_flight_requests_.size() > in_flight_delayable_count_; |
605 if (have_immediate_requests_in_flight && !has_body_ && | 654 if (have_immediate_requests_in_flight && |
606 num_delayable_requests_in_flight != 0) { | 655 total_layout_blocking_count_ != 0 && |
656 in_flight_delayable_count_ != 0) { | |
607 return DO_NOT_START_REQUEST_AND_STOP_SEARCHING; | 657 return DO_NOT_START_REQUEST_AND_STOP_SEARCHING; |
608 } | 658 } |
609 | 659 |
610 return START_REQUEST; | 660 return START_REQUEST; |
611 } | 661 } |
612 | 662 |
613 void LoadAnyStartablePendingRequests() { | 663 void LoadAnyStartablePendingRequests() { |
614 // We iterate through all the pending requests, starting with the highest | 664 // We iterate through all the pending requests, starting with the highest |
615 // priority one. For each entry, one of three things can happen: | 665 // priority one. For each entry, one of three things can happen: |
616 // 1) We start the request, remove it from the list, and keep checking. | 666 // 1) We start the request, remove it from the list, and keep checking. |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
650 bool is_audible_; | 700 bool is_audible_; |
651 bool is_visible_; | 701 bool is_visible_; |
652 bool is_loaded_; | 702 bool is_loaded_; |
653 bool is_paused_; | 703 bool is_paused_; |
654 bool has_body_; | 704 bool has_body_; |
655 bool using_spdy_proxy_; | 705 bool using_spdy_proxy_; |
656 RequestQueue pending_requests_; | 706 RequestQueue pending_requests_; |
657 RequestSet in_flight_requests_; | 707 RequestSet in_flight_requests_; |
658 ResourceScheduler* scheduler_; | 708 ResourceScheduler* scheduler_; |
659 // The number of delayable in-flight requests. | 709 // The number of delayable in-flight requests. |
660 size_t total_delayable_count_; | 710 size_t in_flight_delayable_count_; |
711 // The number of layout-blocking in-flight requests. | |
712 size_t total_layout_blocking_count_; | |
661 ResourceScheduler::ClientThrottleState throttle_state_; | 713 ResourceScheduler::ClientThrottleState throttle_state_; |
662 }; | 714 }; |
663 | 715 |
664 ResourceScheduler::ResourceScheduler() | 716 ResourceScheduler::ResourceScheduler() |
665 : should_coalesce_(false), | 717 : should_coalesce_(false), |
666 should_throttle_(false), | 718 should_throttle_(false), |
667 active_clients_loading_(0), | 719 active_clients_loading_(0), |
668 coalesced_clients_(0), | 720 coalesced_clients_(0), |
669 coalescing_timer_(new base::Timer(true /* retain_user_task */, | 721 coalescing_timer_(new base::Timer(true /* retain_user_task */, |
670 true /* is_repeating */)) { | 722 true /* is_repeating */)) { |
(...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
960 client->ReprioritizeRequest( | 1012 client->ReprioritizeRequest( |
961 request, old_priority_params, new_priority_params); | 1013 request, old_priority_params, new_priority_params); |
962 } | 1014 } |
963 | 1015 |
964 ResourceScheduler::ClientId ResourceScheduler::MakeClientId( | 1016 ResourceScheduler::ClientId ResourceScheduler::MakeClientId( |
965 int child_id, int route_id) { | 1017 int child_id, int route_id) { |
966 return (static_cast<ResourceScheduler::ClientId>(child_id) << 32) | route_id; | 1018 return (static_cast<ResourceScheduler::ClientId>(child_id) << 32) | route_id; |
967 } | 1019 } |
968 | 1020 |
969 } // namespace content | 1021 } // namespace content |
OLD | NEW |