Chromium Code Reviews| 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 category_(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 RequestCategory category() const { |
| 163 return accounted_as_delayable_request_; | 163 return category_; |
| 164 } | 164 } |
| 165 void set_accounted_as_delayable_request(bool accounted) { | 165 void set_category(RequestCategory category) { |
| 166 accounted_as_delayable_request_ = accounted; | 166 category_ = category; |
| 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 RequestCategory category_; | |
| 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 // Keep track of all layout-blocking requests, not just ones that are | |
| 262 // in-flight. StartRequest() updates the accounting for ones that are | |
| 263 // in-flight and this catches the ones that are queued. The accounting | |
| 264 // needs to be done after it is in the queue so the DCHECK to validate | |
| 265 // the counts is accurate. | |
| 266 if (GetRequestCategory(request) == LAYOUT_BLOCKING_REQUEST) | |
| 267 SetRequestCategory(request, LAYOUT_BLOCKING_REQUEST); | |
| 261 } | 268 } |
| 262 } | 269 } |
| 263 | 270 |
| 264 void RemoveRequest(ScheduledResourceRequest* request) { | 271 void RemoveRequest(ScheduledResourceRequest* request) { |
| 265 if (pending_requests_.IsQueued(request)) { | 272 if (pending_requests_.IsQueued(request)) { |
| 266 pending_requests_.Erase(request); | 273 pending_requests_.Erase(request); |
| 267 DCHECK(!ContainsKey(in_flight_requests_, request)); | 274 DCHECK(!ContainsKey(in_flight_requests_, request)); |
| 268 } else { | 275 } else { |
| 269 EraseInFlightRequest(request); | 276 EraseInFlightRequest(request); |
| 270 | 277 |
| 271 // Removing this request may have freed up another to load. | 278 // Removing this request may have freed up another to load. |
| 272 LoadAnyStartablePendingRequests(); | 279 LoadAnyStartablePendingRequests(); |
| 273 } | 280 } |
| 274 } | 281 } |
| 275 | 282 |
| 276 RequestSet RemoveAllRequests() { | 283 RequestSet RemoveAllRequests() { |
| 277 RequestSet unowned_requests; | 284 RequestSet unowned_requests; |
| 278 for (RequestSet::iterator it = in_flight_requests_.begin(); | 285 for (RequestSet::iterator it = in_flight_requests_.begin(); |
| 279 it != in_flight_requests_.end(); ++it) { | 286 it != in_flight_requests_.end(); ++it) { |
| 280 unowned_requests.insert(*it); | 287 unowned_requests.insert(*it); |
| 281 (*it)->set_accounted_as_delayable_request(false); | 288 (*it)->set_category(NORMAL_REQUEST); |
| 282 } | 289 } |
| 283 ClearInFlightRequests(); | 290 ClearInFlightRequests(); |
| 284 return unowned_requests; | 291 return unowned_requests; |
| 285 } | 292 } |
| 286 | 293 |
| 287 bool is_active() const { return is_visible_ || is_audible_; } | 294 bool is_active() const { return is_visible_ || is_audible_; } |
| 288 | 295 |
| 289 bool is_loaded() const { return is_loaded_; } | 296 bool is_loaded() const { return is_loaded_; } |
| 290 | 297 |
| 291 void OnAudibilityChanged(bool is_audible) { | 298 void OnAudibilityChanged(bool is_audible) { |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 367 | 374 |
| 368 void ReprioritizeRequest(ScheduledResourceRequest* request, | 375 void ReprioritizeRequest(ScheduledResourceRequest* request, |
| 369 RequestPriorityParams old_priority_params, | 376 RequestPriorityParams old_priority_params, |
| 370 RequestPriorityParams new_priority_params) { | 377 RequestPriorityParams new_priority_params) { |
| 371 request->url_request()->SetPriority(new_priority_params.priority); | 378 request->url_request()->SetPriority(new_priority_params.priority); |
| 372 request->set_request_priority_params(new_priority_params); | 379 request->set_request_priority_params(new_priority_params); |
| 373 if (!pending_requests_.IsQueued(request)) { | 380 if (!pending_requests_.IsQueued(request)) { |
| 374 DCHECK(ContainsKey(in_flight_requests_, request)); | 381 DCHECK(ContainsKey(in_flight_requests_, request)); |
| 375 // The priority and SPDY support may have changed, so update the | 382 // The priority and SPDY support may have changed, so update the |
| 376 // delayable count. | 383 // delayable count. |
| 377 SetRequestDelayable(request, IsDelayableRequest(request)); | 384 SetRequestCategory(request, GetRequestCategory(request)); |
| 378 // Request has already started. | 385 // Request has already started. |
| 379 return; | 386 return; |
| 380 } | 387 } |
| 381 | 388 |
| 382 pending_requests_.Erase(request); | 389 pending_requests_.Erase(request); |
| 383 pending_requests_.Insert(request); | 390 pending_requests_.Insert(request); |
| 384 | 391 |
| 385 if (new_priority_params.priority > old_priority_params.priority) { | 392 if (new_priority_params.priority > old_priority_params.priority) { |
| 386 // Check if this request is now able to load at its new priority. | 393 // Check if this request is now able to load at its new priority. |
| 387 LoadAnyStartablePendingRequests(); | 394 LoadAnyStartablePendingRequests(); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 434 | 441 |
| 435 private: | 442 private: |
| 436 enum ShouldStartReqResult { | 443 enum ShouldStartReqResult { |
| 437 DO_NOT_START_REQUEST_AND_STOP_SEARCHING, | 444 DO_NOT_START_REQUEST_AND_STOP_SEARCHING, |
| 438 DO_NOT_START_REQUEST_AND_KEEP_SEARCHING, | 445 DO_NOT_START_REQUEST_AND_KEEP_SEARCHING, |
| 439 START_REQUEST, | 446 START_REQUEST, |
| 440 }; | 447 }; |
| 441 | 448 |
| 442 void InsertInFlightRequest(ScheduledResourceRequest* request) { | 449 void InsertInFlightRequest(ScheduledResourceRequest* request) { |
| 443 in_flight_requests_.insert(request); | 450 in_flight_requests_.insert(request); |
| 444 if (IsDelayableRequest(request)) | 451 SetRequestCategory(request, GetRequestCategory(request)); |
| 445 SetRequestDelayable(request, true); | |
| 446 } | 452 } |
| 447 | 453 |
| 448 void EraseInFlightRequest(ScheduledResourceRequest* request) { | 454 void EraseInFlightRequest(ScheduledResourceRequest* request) { |
| 449 size_t erased = in_flight_requests_.erase(request); | 455 size_t erased = in_flight_requests_.erase(request); |
| 450 DCHECK_EQ(1u, erased); | 456 DCHECK_EQ(1u, erased); |
| 451 SetRequestDelayable(request, false); | 457 // Clear any special state that we were tracking for this request. |
| 452 DCHECK_LE(total_delayable_count_, in_flight_requests_.size()); | 458 SetRequestCategory(request, NORMAL_REQUEST); |
| 453 } | 459 } |
| 454 | 460 |
| 455 void ClearInFlightRequests() { | 461 void ClearInFlightRequests() { |
| 456 in_flight_requests_.clear(); | 462 in_flight_requests_.clear(); |
| 457 total_delayable_count_ = 0; | 463 in_flight_delayable_count_ = 0; |
| 464 total_layout_blocking_count_ = 0; | |
| 458 } | 465 } |
| 459 | 466 |
| 460 bool IsDelayableRequest(ScheduledResourceRequest* request) { | 467 size_t CountRequestsInCategory(const RequestCategory category, |
| 468 const bool include_pending) { | |
| 469 size_t category_request_count = 0; | |
| 470 for (RequestSet::const_iterator it = in_flight_requests_.begin(); | |
| 471 it != in_flight_requests_.end(); ++it) { | |
| 472 if ((*it)->category() == category) | |
| 473 category_request_count++; | |
| 474 } | |
| 475 if (include_pending) { | |
| 476 for (RequestQueue::NetQueue::const_iterator | |
| 477 it = pending_requests_.GetNextHighestIterator(); | |
| 478 it != pending_requests_.End(); ++it) { | |
| 479 if ((*it)->category() == category) | |
| 480 category_request_count++; | |
| 481 } | |
| 482 } | |
| 483 return category_request_count; | |
| 484 } | |
| 485 | |
| 486 void SetRequestCategory(ScheduledResourceRequest* request, | |
| 487 RequestCategory category) { | |
| 488 RequestCategory old_category = request->category(); | |
| 489 if (old_category == category) | |
| 490 return; | |
| 491 | |
| 492 if (old_category == DELAYABLE_REQUEST) | |
| 493 in_flight_delayable_count_--; | |
| 494 if (old_category == LAYOUT_BLOCKING_REQUEST) | |
| 495 total_layout_blocking_count_--; | |
| 496 | |
| 497 if (category == DELAYABLE_REQUEST) | |
| 498 in_flight_delayable_count_++; | |
| 499 if (category == LAYOUT_BLOCKING_REQUEST) | |
| 500 total_layout_blocking_count_++; | |
| 501 | |
| 502 request->set_category(category); | |
| 503 DCHECK_EQ(CountRequestsInCategory(DELAYABLE_REQUEST, false), | |
| 504 in_flight_delayable_count_); | |
| 505 DCHECK_EQ(CountRequestsInCategory(LAYOUT_BLOCKING_REQUEST, true), | |
| 506 total_layout_blocking_count_); | |
| 507 } | |
| 508 | |
| 509 RequestCategory GetRequestCategory(ScheduledResourceRequest* request) { | |
| 510 // If a request is already marked as layout-blocking make sure to keep the | |
| 511 // category across redirects unless the priority was lowered. | |
| 512 if (request->category() == LAYOUT_BLOCKING_REQUEST && | |
| 513 request->url_request()->priority() >= net::LOW) { | |
| 514 return LAYOUT_BLOCKING_REQUEST; | |
| 515 } | |
| 516 | |
| 517 if (!has_body_ && request->url_request()->priority() >= net::LOW) | |
| 518 return LAYOUT_BLOCKING_REQUEST; | |
| 461 if (request->url_request()->priority() < net::LOW) { | 519 if (request->url_request()->priority() < net::LOW) { |
| 462 net::HostPortPair host_port_pair = | 520 net::HostPortPair host_port_pair = |
| 463 net::HostPortPair::FromURL(request->url_request()->url()); | 521 net::HostPortPair::FromURL(request->url_request()->url()); |
| 464 net::HttpServerProperties& http_server_properties = | 522 net::HttpServerProperties& http_server_properties = |
| 465 *request->url_request()->context()->http_server_properties(); | 523 *request->url_request()->context()->http_server_properties(); |
| 466 if (!http_server_properties.SupportsSpdy(host_port_pair)) { | 524 if (!http_server_properties.SupportsSpdy(host_port_pair)) { |
| 467 return true; | 525 return DELAYABLE_REQUEST; |
| 468 } | 526 } |
| 469 } | 527 } |
| 470 return false; | 528 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 } | 529 } |
| 483 | 530 |
| 484 bool ShouldKeepSearching( | 531 bool ShouldKeepSearching( |
| 485 const net::HostPortPair& active_request_host) const { | 532 const net::HostPortPair& active_request_host) const { |
| 486 size_t same_host_count = 0; | 533 size_t same_host_count = 0; |
| 487 for (RequestSet::const_iterator it = in_flight_requests_.begin(); | 534 for (RequestSet::const_iterator it = in_flight_requests_.begin(); |
| 488 it != in_flight_requests_.end(); ++it) { | 535 it != in_flight_requests_.end(); ++it) { |
| 489 net::HostPortPair host_port_pair = | 536 net::HostPortPair host_port_pair = |
| 490 net::HostPortPair::FromURL((*it)->url_request()->url()); | 537 net::HostPortPair::FromURL((*it)->url_request()->url()); |
| 491 if (active_request_host.Equals(host_port_pair)) { | 538 if (active_request_host.Equals(host_port_pair)) { |
| 492 same_host_count++; | 539 same_host_count++; |
| 493 if (same_host_count >= kMaxNumDelayableRequestsPerHost) | 540 if (same_host_count >= kMaxNumDelayableRequestsPerHost) |
| 494 return true; | 541 return true; |
| 495 } | 542 } |
| 496 } | 543 } |
| 497 return false; | 544 return false; |
| 498 } | 545 } |
| 499 | 546 |
| 500 void StartRequest(ScheduledResourceRequest* request) { | 547 void StartRequest(ScheduledResourceRequest* request) { |
| 501 InsertInFlightRequest(request); | 548 InsertInFlightRequest(request); |
| 502 request->Start(); | 549 request->Start(); |
| 503 } | 550 } |
| 504 | 551 |
| 505 // ShouldStartRequest is the main scheduling algorithm. | 552 // ShouldStartRequest is the main scheduling algorithm. |
| 506 // | 553 // |
| 507 // Requests are categorized into three categories: | 554 // Requests are categorized into five categories: |
|
mmenke
2014/08/18 16:30:20
Think it's worth noting these are not mutually exc
Pat Meenan
2014/08/18 18:29:57
Done. (changed the language to say it evaluates re
| |
| 508 // | 555 // |
| 509 // 1. Non-delayable requests: | 556 // 1. Non-delayable requests: |
| 510 // * Synchronous requests. | 557 // * Synchronous requests. |
| 511 // * Non-HTTP[S] requests. | 558 // * Non-HTTP[S] requests. |
| 512 // | 559 // |
| 513 // 2. Requests to SPDY-capable origin servers. | 560 // 2. Requests to SPDY-capable origin servers. |
| 514 // | 561 // |
| 515 // 3. High-priority requests: | 562 // 3. High-priority requests: |
| 516 // * Higher priority requests (>= net::LOW). | 563 // * Higher priority requests (>= net::LOW). |
| 517 // | 564 // |
| 518 // 4. Low priority requests | 565 // 4. Layout-blocking requests: |
| 566 // * High-priority requests initiated before the renderer has a <body>. | |
| 567 // | |
| 568 // 5. Low priority requests | |
| 519 // | 569 // |
| 520 // The following rules are followed: | 570 // The following rules are followed: |
| 521 // | 571 // |
| 522 // ACTIVE_AND_LOADING and UNTHROTTLED Clients follow these rules: | 572 // ACTIVE_AND_LOADING and UNTHROTTLED Clients follow these rules: |
| 523 // * Non-delayable, High-priority and SDPY capable requests are issued | 573 // * Non-delayable, High-priority and SPDY capable requests are issued |
| 524 // immediately | 574 // immediately. |
| 525 // * If no high priority requests are in flight, start loading low priority | 575 // * If no high priority requests are in flight, start loading low priority |
| 526 // requests. | 576 // requests. |
|
mmenke
2014/08/18 16:30:20
This seems redundant with the two you added/modifi
Pat Meenan
2014/08/18 18:29:57
Done.
| |
| 527 // * Low priority requests are delayable. | 577 // * Low priority requests are delayable. |
| 528 // * Once the renderer has a <body>, start loading delayable requests. | 578 // * Allow one delayable request to load at a time while layout-blocking |
| 579 // requests are loading. | |
| 580 // * Once all layout-blocking requests have finished loading, start loading | |
| 581 // delayable requests. | |
| 529 // * Never exceed 10 delayable requests in flight per client. | 582 // * Never exceed 10 delayable requests in flight per client. |
| 530 // * Never exceed 6 delayable requests for a given host. | 583 // * Never exceed 6 delayable requests for a given host. |
| 531 // * Prior to <body>, allow one delayable request to load at a time. | |
| 532 // | 584 // |
| 533 // THROTTLED Clients follow these rules: | 585 // THROTTLED Clients follow these rules: |
| 534 // * Non-delayable and SPDY-capable requests are issued immediately. | 586 // * Non-delayable and SPDY-capable requests are issued immediately. |
| 535 // * At most one non-SPDY request will be issued per THROTTLED Client | 587 // * 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 | 588 // * If no high priority requests are in flight, start loading low priority |
| 537 // requests. | 589 // requests. |
| 538 // | 590 // |
| 539 // COALESCED Clients never load requests, with the following exceptions: | 591 // COALESCED Clients never load requests, with the following exceptions: |
| 540 // * Non-delayable requests are issued imediately. | 592 // * Non-delayable requests are issued imediately. |
| 541 // * On a (currently 5 second) heart beat, they load all requests as an | 593 // * 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)) { | 630 if (http_server_properties.SupportsSpdy(host_port_pair)) { |
| 579 return START_REQUEST; | 631 return START_REQUEST; |
| 580 } | 632 } |
| 581 | 633 |
| 582 if (throttle_state_ == THROTTLED && | 634 if (throttle_state_ == THROTTLED && |
| 583 in_flight_requests_.size() >= kMaxNumThrottledRequestsPerClient) { | 635 in_flight_requests_.size() >= kMaxNumThrottledRequestsPerClient) { |
| 584 // There may still be SPDY-capable requests that should be issued. | 636 // There may still be SPDY-capable requests that should be issued. |
| 585 return DO_NOT_START_REQUEST_AND_KEEP_SEARCHING; | 637 return DO_NOT_START_REQUEST_AND_KEEP_SEARCHING; |
| 586 } | 638 } |
| 587 | 639 |
| 640 // High-priority and layout-blocking requests. | |
| 588 if (url_request.priority() >= net::LOW) { | 641 if (url_request.priority() >= net::LOW) { |
| 589 return START_REQUEST; | 642 return START_REQUEST; |
| 590 } | 643 } |
| 591 | 644 |
| 592 size_t num_delayable_requests_in_flight = total_delayable_count_; | 645 if (in_flight_delayable_count_ >= kMaxNumDelayableRequestsPerClient) { |
| 593 if (num_delayable_requests_in_flight >= kMaxNumDelayableRequestsPerClient) { | |
| 594 return DO_NOT_START_REQUEST_AND_STOP_SEARCHING; | 646 return DO_NOT_START_REQUEST_AND_STOP_SEARCHING; |
| 595 } | 647 } |
| 596 | 648 |
| 597 if (ShouldKeepSearching(host_port_pair)) { | 649 if (ShouldKeepSearching(host_port_pair)) { |
| 598 // There may be other requests for other hosts we'd allow, | 650 // There may be other requests for other hosts we'd allow, |
| 599 // so keep checking. | 651 // so keep checking. |
| 600 return DO_NOT_START_REQUEST_AND_KEEP_SEARCHING; | 652 return DO_NOT_START_REQUEST_AND_KEEP_SEARCHING; |
| 601 } | 653 } |
| 602 | 654 |
| 603 bool have_immediate_requests_in_flight = | 655 bool have_immediate_requests_in_flight = |
| 604 in_flight_requests_.size() > num_delayable_requests_in_flight; | 656 in_flight_requests_.size() > in_flight_delayable_count_; |
| 605 if (have_immediate_requests_in_flight && !has_body_ && | 657 if (have_immediate_requests_in_flight && |
| 606 num_delayable_requests_in_flight != 0) { | 658 total_layout_blocking_count_ != 0 && |
| 659 in_flight_delayable_count_ != 0) { | |
| 607 return DO_NOT_START_REQUEST_AND_STOP_SEARCHING; | 660 return DO_NOT_START_REQUEST_AND_STOP_SEARCHING; |
| 608 } | 661 } |
| 609 | 662 |
| 610 return START_REQUEST; | 663 return START_REQUEST; |
| 611 } | 664 } |
| 612 | 665 |
| 613 void LoadAnyStartablePendingRequests() { | 666 void LoadAnyStartablePendingRequests() { |
| 614 // We iterate through all the pending requests, starting with the highest | 667 // We iterate through all the pending requests, starting with the highest |
| 615 // priority one. For each entry, one of three things can happen: | 668 // 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. | 669 // 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_; | 703 bool is_audible_; |
| 651 bool is_visible_; | 704 bool is_visible_; |
| 652 bool is_loaded_; | 705 bool is_loaded_; |
| 653 bool is_paused_; | 706 bool is_paused_; |
| 654 bool has_body_; | 707 bool has_body_; |
| 655 bool using_spdy_proxy_; | 708 bool using_spdy_proxy_; |
| 656 RequestQueue pending_requests_; | 709 RequestQueue pending_requests_; |
| 657 RequestSet in_flight_requests_; | 710 RequestSet in_flight_requests_; |
| 658 ResourceScheduler* scheduler_; | 711 ResourceScheduler* scheduler_; |
| 659 // The number of delayable in-flight requests. | 712 // The number of delayable in-flight requests. |
| 660 size_t total_delayable_count_; | 713 size_t in_flight_delayable_count_; |
| 714 // The number of layout-blocking in-flight requests. | |
| 715 size_t total_layout_blocking_count_; | |
| 661 ResourceScheduler::ClientThrottleState throttle_state_; | 716 ResourceScheduler::ClientThrottleState throttle_state_; |
| 662 }; | 717 }; |
| 663 | 718 |
| 664 ResourceScheduler::ResourceScheduler() | 719 ResourceScheduler::ResourceScheduler() |
| 665 : should_coalesce_(false), | 720 : should_coalesce_(false), |
| 666 should_throttle_(false), | 721 should_throttle_(false), |
| 667 active_clients_loading_(0), | 722 active_clients_loading_(0), |
| 668 coalesced_clients_(0), | 723 coalesced_clients_(0), |
| 669 coalescing_timer_(new base::Timer(true /* retain_user_task */, | 724 coalescing_timer_(new base::Timer(true /* retain_user_task */, |
| 670 true /* is_repeating */)) { | 725 true /* is_repeating */)) { |
| (...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 960 client->ReprioritizeRequest( | 1015 client->ReprioritizeRequest( |
| 961 request, old_priority_params, new_priority_params); | 1016 request, old_priority_params, new_priority_params); |
| 962 } | 1017 } |
| 963 | 1018 |
| 964 ResourceScheduler::ClientId ResourceScheduler::MakeClientId( | 1019 ResourceScheduler::ClientId ResourceScheduler::MakeClientId( |
| 965 int child_id, int route_id) { | 1020 int child_id, int route_id) { |
| 966 return (static_cast<ResourceScheduler::ClientId>(child_id) << 32) | route_id; | 1021 return (static_cast<ResourceScheduler::ClientId>(child_id) << 32) | route_id; |
| 967 } | 1022 } |
| 968 | 1023 |
| 969 } // namespace content | 1024 } // namespace content |
| OLD | NEW |