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 "content/browser/loader/resource_scheduler.h" | |
| 5 #include <set> | 6 #include <set> |
| 6 | 7 |
| 7 #include "content/browser/loader/resource_scheduler.h" | |
| 8 | |
| 9 #include "base/metrics/field_trial.h" | 8 #include "base/metrics/field_trial.h" |
| 10 #include "base/metrics/histogram.h" | 9 #include "base/metrics/histogram.h" |
| 11 #include "base/stl_util.h" | 10 #include "base/stl_util.h" |
| 12 #include "base/strings/string_number_conversions.h" | 11 #include "base/strings/string_number_conversions.h" |
| 13 #include "base/strings/string_piece.h" | 12 #include "base/strings/string_piece.h" |
| 14 #include "base/time/time.h" | 13 #include "base/time/time.h" |
| 15 #include "content/common/resource_messages.h" | 14 #include "content/common/resource_messages.h" |
| 16 #include "content/browser/loader/resource_message_delegate.h" | 15 #include "content/browser/loader/resource_message_delegate.h" |
| 17 #include "content/public/browser/resource_controller.h" | 16 #include "content/public/browser/resource_controller.h" |
| 18 #include "content/public/browser/resource_request_info.h" | 17 #include "content/public/browser/resource_request_info.h" |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 30 namespace { | 29 namespace { |
| 31 | 30 |
| 32 // Field trial constants | 31 // Field trial constants |
| 33 const char kThrottleCoalesceFieldTrial[] = "RequestThrottlingAndCoalescing"; | 32 const char kThrottleCoalesceFieldTrial[] = "RequestThrottlingAndCoalescing"; |
| 34 const char kThrottleCoalesceFieldTrialThrottle[] = "Throttle"; | 33 const char kThrottleCoalesceFieldTrialThrottle[] = "Throttle"; |
| 35 const char kThrottleCoalesceFieldTrialCoalesce[] = "Coalesce"; | 34 const char kThrottleCoalesceFieldTrialCoalesce[] = "Coalesce"; |
| 36 | 35 |
| 37 const char kRequestLimitFieldTrial[] = "OutstandingRequestLimiting"; | 36 const char kRequestLimitFieldTrial[] = "OutstandingRequestLimiting"; |
| 38 const char kRequestLimitFieldTrialGroupPrefix[] = "Limit"; | 37 const char kRequestLimitFieldTrialGroupPrefix[] = "Limit"; |
| 39 | 38 |
| 39 const char kResourcePrioritiesFieldTrial[] = "ResourcePriorities"; | |
| 40 | |
| 40 // Post ResourceScheduler histograms of the following forms: | 41 // Post ResourceScheduler histograms of the following forms: |
| 41 // If |histogram_suffix| is NULL or the empty string: | 42 // If |histogram_suffix| is NULL or the empty string: |
| 42 // ResourceScheduler.base_name.histogram_name | 43 // ResourceScheduler.base_name.histogram_name |
| 43 // Else: | 44 // Else: |
| 44 // ResourceScheduler.base_name.histogram_name.histogram_suffix | 45 // ResourceScheduler.base_name.histogram_name.histogram_suffix |
| 45 void PostHistogram(const char* base_name, | 46 void PostHistogram(const char* base_name, |
| 46 const char* histogram_name, | 47 const char* histogram_name, |
| 47 const char* histogram_suffix, | 48 const char* histogram_suffix, |
| 48 base::TimeDelta time) { | 49 base::TimeDelta time) { |
| 49 std::string histogram = | 50 std::string histogram = |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 67 else if (num_clients <= 15) | 68 else if (num_clients <= 15) |
| 68 return "Max15Clients"; | 69 return "Max15Clients"; |
| 69 else if (num_clients <= 30) | 70 else if (num_clients <= 30) |
| 70 return "Max30Clients"; | 71 return "Max30Clients"; |
| 71 return "Over30Clients"; | 72 return "Over30Clients"; |
| 72 } | 73 } |
| 73 | 74 |
| 74 } // namespace | 75 } // namespace |
| 75 | 76 |
| 76 static const size_t kCoalescedTimerPeriod = 5000; | 77 static const size_t kCoalescedTimerPeriod = 5000; |
| 77 static const size_t kMaxNumDelayableRequestsPerClient = 10; | 78 static const size_t kDefaultMaxNumDelayableRequestsPerClient = 10; |
| 78 static const size_t kMaxNumDelayableRequestsPerHost = 6; | 79 static const size_t kMaxNumDelayableRequestsPerHost = 6; |
| 79 static const size_t kMaxNumThrottledRequestsPerClient = 1; | 80 static const size_t kMaxNumThrottledRequestsPerClient = 1; |
| 81 static const size_t kDefaultMaxNumDelayableWhileLayoutBlocking = 1; | |
| 82 static const net::RequestPriority | |
| 83 kDefaultLayoutBlockingPriorityThreshold = net::LOW; | |
| 80 | 84 |
| 81 struct ResourceScheduler::RequestPriorityParams { | 85 struct ResourceScheduler::RequestPriorityParams { |
| 82 RequestPriorityParams() | 86 RequestPriorityParams() |
| 83 : priority(net::DEFAULT_PRIORITY), | 87 : priority(net::DEFAULT_PRIORITY), |
| 84 intra_priority(0) { | 88 intra_priority(0) { |
| 85 } | 89 } |
| 86 | 90 |
| 87 RequestPriorityParams(net::RequestPriority priority, int intra_priority) | 91 RequestPriorityParams(net::RequestPriority priority, int intra_priority) |
| 88 : priority(priority), | 92 : priority(priority), |
| 89 intra_priority(intra_priority) { | 93 intra_priority(intra_priority) { |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 296 DCHECK(!ContainsKey(pointers_, request)); | 300 DCHECK(!ContainsKey(pointers_, request)); |
| 297 request->set_fifo_ordering(MakeFifoOrderingId()); | 301 request->set_fifo_ordering(MakeFifoOrderingId()); |
| 298 pointers_[request] = queue_.insert(request); | 302 pointers_[request] = queue_.insert(request); |
| 299 } | 303 } |
| 300 | 304 |
| 301 // Each client represents a tab. | 305 // Each client represents a tab. |
| 302 class ResourceScheduler::Client { | 306 class ResourceScheduler::Client { |
| 303 public: | 307 public: |
| 304 explicit Client(ResourceScheduler* scheduler, | 308 explicit Client(ResourceScheduler* scheduler, |
| 305 bool is_visible, | 309 bool is_visible, |
| 306 bool is_audible) | 310 bool is_audible, |
| 311 net::RequestPriority layout_blocking_priority_threshold, | |
| 312 bool enable_layout_blocking_threshold, | |
| 313 size_t in_flight_layout_blocking_threshold, | |
| 314 size_t max_num_delayable_while_layout_blocking, | |
| 315 size_t max_num_delayable_requests) | |
| 307 : is_audible_(is_audible), | 316 : is_audible_(is_audible), |
| 308 is_visible_(is_visible), | 317 is_visible_(is_visible), |
| 309 is_loaded_(false), | 318 is_loaded_(false), |
| 310 is_paused_(false), | 319 is_paused_(false), |
| 311 has_body_(false), | 320 has_html_body_(false), |
| 312 using_spdy_proxy_(false), | 321 using_spdy_proxy_(false), |
| 313 load_started_time_(base::TimeTicks::Now()), | 322 load_started_time_(base::TimeTicks::Now()), |
| 314 scheduler_(scheduler), | 323 scheduler_(scheduler), |
| 315 in_flight_delayable_count_(0), | 324 in_flight_delayable_count_(0), |
| 316 total_layout_blocking_count_(0), | 325 total_layout_blocking_count_(0), |
| 317 throttle_state_(ResourceScheduler::THROTTLED) {} | 326 throttle_state_(ResourceScheduler::THROTTLED), |
| 327 max_num_delayable_requests_(max_num_delayable_requests), | |
| 328 max_num_delayable_while_layout_blocking_( | |
| 329 max_num_delayable_while_layout_blocking), | |
| 330 enable_layout_blocking_threshold_(enable_layout_blocking_threshold), | |
| 331 in_flight_layout_blocking_threshold_( | |
| 332 in_flight_layout_blocking_threshold), | |
| 333 layout_blocking_priority_threshold_( | |
| 334 layout_blocking_priority_threshold) { | |
| 335 } | |
| 318 | 336 |
| 319 ~Client() { | 337 ~Client() { |
| 320 // Update to default state and pause to ensure the scheduler has a | 338 // Update to default state and pause to ensure the scheduler has a |
| 321 // correct count of relevant types of clients. | 339 // correct count of relevant types of clients. |
| 322 is_visible_ = false; | 340 is_visible_ = false; |
| 323 is_audible_ = false; | 341 is_audible_ = false; |
| 324 is_paused_ = true; | 342 is_paused_ = true; |
| 325 UpdateThrottleState(); | 343 UpdateThrottleState(); |
| 326 } | 344 } |
| 327 | 345 |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 343 EraseInFlightRequest(request); | 361 EraseInFlightRequest(request); |
| 344 | 362 |
| 345 // Removing this request may have freed up another to load. | 363 // Removing this request may have freed up another to load. |
| 346 LoadAnyStartablePendingRequests(); | 364 LoadAnyStartablePendingRequests(); |
| 347 } | 365 } |
| 348 } | 366 } |
| 349 | 367 |
| 350 RequestSet StartAndRemoveAllRequests() { | 368 RequestSet StartAndRemoveAllRequests() { |
| 351 // First start any pending requests so that they will be moved into | 369 // First start any pending requests so that they will be moved into |
| 352 // in_flight_requests_. This may exceed the limits | 370 // in_flight_requests_. This may exceed the limits |
| 353 // kMaxNumDelayableRequestsPerClient, kMaxNumDelayableRequestsPerHost and | 371 // kDefaultMaxNumDelayableRequestsPerClient, kMaxNumDelayableRequestsPerHost |
| 354 // kMaxNumThrottledRequestsPerClient, so this method must not do anything | 372 // and kMaxNumThrottledRequestsPerClient, so this method must not do |
| 355 // that depends on those limits before calling ClearInFlightRequests() | 373 // anything that depends on those limits before calling |
| 356 // below. | 374 // ClearInFlightRequests() below. |
| 357 while (!pending_requests_.IsEmpty()) { | 375 while (!pending_requests_.IsEmpty()) { |
| 358 ScheduledResourceRequest* request = | 376 ScheduledResourceRequest* request = |
| 359 *pending_requests_.GetNextHighestIterator(); | 377 *pending_requests_.GetNextHighestIterator(); |
| 360 pending_requests_.Erase(request); | 378 pending_requests_.Erase(request); |
| 361 // StartRequest() may modify pending_requests_. TODO(ricea): Does it? | 379 // StartRequest() may modify pending_requests_. TODO(ricea): Does it? |
| 362 StartRequest(request); | 380 StartRequest(request); |
| 363 } | 381 } |
| 364 RequestSet unowned_requests; | 382 RequestSet unowned_requests; |
| 365 for (RequestSet::iterator it = in_flight_requests_.begin(); | 383 for (RequestSet::iterator it = in_flight_requests_.begin(); |
| 366 it != in_flight_requests_.end(); ++it) { | 384 it != in_flight_requests_.end(); ++it) { |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 463 scheduler_->DecrementActiveClientsLoading(); | 481 scheduler_->DecrementActiveClientsLoading(); |
| 464 } | 482 } |
| 465 if (throttle_state_ == COALESCED) { | 483 if (throttle_state_ == COALESCED) { |
| 466 scheduler_->IncrementCoalescedClients(); | 484 scheduler_->IncrementCoalescedClients(); |
| 467 } else if (old_throttle_state == COALESCED) { | 485 } else if (old_throttle_state == COALESCED) { |
| 468 scheduler_->DecrementCoalescedClients(); | 486 scheduler_->DecrementCoalescedClients(); |
| 469 } | 487 } |
| 470 } | 488 } |
| 471 | 489 |
| 472 void OnNavigate() { | 490 void OnNavigate() { |
| 473 has_body_ = false; | 491 has_html_body_ = false; |
| 474 is_loaded_ = false; | 492 is_loaded_ = false; |
| 475 } | 493 } |
| 476 | 494 |
| 477 void OnWillInsertBody() { | 495 void OnWillInsertBody() { |
| 478 has_body_ = true; | 496 has_html_body_ = true; |
| 479 LoadAnyStartablePendingRequests(); | 497 LoadAnyStartablePendingRequests(); |
| 480 } | 498 } |
| 481 | 499 |
| 482 void OnReceivedSpdyProxiedHttpResponse() { | 500 void OnReceivedSpdyProxiedHttpResponse() { |
| 483 if (!using_spdy_proxy_) { | 501 if (!using_spdy_proxy_) { |
| 484 using_spdy_proxy_ = true; | 502 using_spdy_proxy_ = true; |
| 485 LoadAnyStartablePendingRequests(); | 503 LoadAnyStartablePendingRequests(); |
| 486 } | 504 } |
| 487 } | 505 } |
| 488 | 506 |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 618 CountRequestsWithClassification(IN_FLIGHT_DELAYABLE_REQUEST, false), | 636 CountRequestsWithClassification(IN_FLIGHT_DELAYABLE_REQUEST, false), |
| 619 in_flight_delayable_count_); | 637 in_flight_delayable_count_); |
| 620 DCHECK_EQ(CountRequestsWithClassification(LAYOUT_BLOCKING_REQUEST, true), | 638 DCHECK_EQ(CountRequestsWithClassification(LAYOUT_BLOCKING_REQUEST, true), |
| 621 total_layout_blocking_count_); | 639 total_layout_blocking_count_); |
| 622 } | 640 } |
| 623 | 641 |
| 624 RequestClassification ClassifyRequest(ScheduledResourceRequest* request) { | 642 RequestClassification ClassifyRequest(ScheduledResourceRequest* request) { |
| 625 // If a request is already marked as layout-blocking make sure to keep the | 643 // If a request is already marked as layout-blocking make sure to keep the |
| 626 // classification across redirects unless the priority was lowered. | 644 // classification across redirects unless the priority was lowered. |
| 627 if (request->classification() == LAYOUT_BLOCKING_REQUEST && | 645 if (request->classification() == LAYOUT_BLOCKING_REQUEST && |
| 628 request->url_request()->priority() > net::LOW) { | 646 request->url_request()->priority() > |
| 647 layout_blocking_priority_threshold_) { | |
| 629 return LAYOUT_BLOCKING_REQUEST; | 648 return LAYOUT_BLOCKING_REQUEST; |
| 630 } | 649 } |
| 631 | 650 |
| 632 if (!has_body_ && request->url_request()->priority() > net::LOW) | 651 if (!has_html_body_ && |
| 652 request->url_request()->priority() > | |
| 653 layout_blocking_priority_threshold_) { | |
| 633 return LAYOUT_BLOCKING_REQUEST; | 654 return LAYOUT_BLOCKING_REQUEST; |
| 655 } | |
| 634 | 656 |
| 635 if (request->url_request()->priority() < net::LOW) { | 657 if (request->url_request()->priority() < |
| 636 net::HostPortPair host_port_pair = | 658 layout_blocking_priority_threshold_ && |
| 637 net::HostPortPair::FromURL(request->url_request()->url()); | 659 ContainsKey(in_flight_requests_, request)) { |
| 638 net::HttpServerProperties& http_server_properties = | 660 return IN_FLIGHT_DELAYABLE_REQUEST; |
| 639 *request->url_request()->context()->http_server_properties(); | |
| 640 if (!http_server_properties.SupportsRequestPriority(host_port_pair) && | |
| 641 ContainsKey(in_flight_requests_, request)) { | |
| 642 return IN_FLIGHT_DELAYABLE_REQUEST; | |
| 643 } | |
| 644 } | 661 } |
| 645 return NORMAL_REQUEST; | 662 return NORMAL_REQUEST; |
| 646 } | 663 } |
| 647 | 664 |
| 648 bool ShouldKeepSearching( | 665 bool ShouldKeepSearching( |
| 649 const net::HostPortPair& active_request_host) const { | 666 const net::HostPortPair& active_request_host) const { |
| 650 size_t same_host_count = 0; | 667 size_t same_host_count = 0; |
| 651 for (RequestSet::const_iterator it = in_flight_requests_.begin(); | 668 for (RequestSet::const_iterator it = in_flight_requests_.begin(); |
| 652 it != in_flight_requests_.end(); ++it) { | 669 it != in_flight_requests_.end(); ++it) { |
| 653 net::HostPortPair host_port_pair = | 670 net::HostPortPair host_port_pair = |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 762 } | 779 } |
| 763 | 780 |
| 764 if (throttle_state_ == THROTTLED && | 781 if (throttle_state_ == THROTTLED && |
| 765 in_flight_requests_.size() >= kMaxNumThrottledRequestsPerClient) { | 782 in_flight_requests_.size() >= kMaxNumThrottledRequestsPerClient) { |
| 766 // There may still be request-priority-capable requests that should be | 783 // There may still be request-priority-capable requests that should be |
| 767 // issued. | 784 // issued. |
| 768 return DO_NOT_START_REQUEST_AND_KEEP_SEARCHING; | 785 return DO_NOT_START_REQUEST_AND_KEEP_SEARCHING; |
| 769 } | 786 } |
| 770 | 787 |
| 771 // High-priority and layout-blocking requests. | 788 // High-priority and layout-blocking requests. |
| 772 if (url_request.priority() >= net::LOW) { | 789 if (url_request.priority() >= layout_blocking_priority_threshold_) { |
| 773 return START_REQUEST; | 790 return START_REQUEST; |
| 774 } | 791 } |
| 775 | 792 |
| 776 if (in_flight_delayable_count_ >= kMaxNumDelayableRequestsPerClient) { | 793 if (in_flight_delayable_count_ >= max_num_delayable_requests_) { |
| 777 return DO_NOT_START_REQUEST_AND_STOP_SEARCHING; | 794 return DO_NOT_START_REQUEST_AND_STOP_SEARCHING; |
| 778 } | 795 } |
| 779 | 796 |
| 780 if (ShouldKeepSearching(host_port_pair)) { | 797 if (ShouldKeepSearching(host_port_pair)) { |
| 781 // There may be other requests for other hosts we'd allow, | 798 // There may be other requests for other hosts we'd allow, |
| 782 // so keep checking. | 799 // so keep checking. |
| 783 return DO_NOT_START_REQUEST_AND_KEEP_SEARCHING; | 800 return DO_NOT_START_REQUEST_AND_KEEP_SEARCHING; |
| 784 } | 801 } |
| 785 | 802 |
| 786 bool have_immediate_requests_in_flight = | 803 // Layout-blocking phase of resource loading. |
| 787 in_flight_requests_.size() > in_flight_delayable_count_; | 804 if (!has_html_body_ || total_layout_blocking_count_ != 0) { |
| 788 if (have_immediate_requests_in_flight && | 805 size_t non_delayable_requests_in_flight_count = |
| 789 (!has_body_ || total_layout_blocking_count_ != 0) && | 806 in_flight_requests_.size() - in_flight_delayable_count_; |
|
Bryan McQuade
2015/08/11 13:25:07
on first glance this is potentially scary since, i
mmenke
2015/08/11 13:35:34
The only place we modify the classification of req
| |
| 790 // Do not allow a low priority request through in parallel if | 807 if (enable_layout_blocking_threshold_) { |
| 791 // we are in a limit field trial. | 808 if (non_delayable_requests_in_flight_count > |
| 792 (scheduler_->limit_outstanding_requests() || | 809 in_flight_layout_blocking_threshold_) { |
| 793 in_flight_delayable_count_ != 0)) { | 810 // Too many higher priority in-flight requests to allow lower priority |
| 794 return DO_NOT_START_REQUEST_AND_STOP_SEARCHING; | 811 // requests through. |
| 812 return DO_NOT_START_REQUEST_AND_STOP_SEARCHING; | |
| 813 } | |
| 814 if (in_flight_requests_.size() > 0 && | |
| 815 // Allow the request if nothing is in flight or if the limit of | |
| 816 // concurrent lower priority requests has not been hit. | |
| 817 (scheduler_->limit_outstanding_requests() || | |
| 818 in_flight_delayable_count_ >= | |
| 819 max_num_delayable_while_layout_blocking_)) { | |
| 820 return DO_NOT_START_REQUEST_AND_STOP_SEARCHING; | |
| 821 } | |
| 822 } else if (non_delayable_requests_in_flight_count > 0 && | |
| 823 // If there are no high-priority requests in flight the floodgates | |
| 824 // open. | |
| 825 // If there are high-priority requests in-flight then limit the number | |
| 826 // of lower-priority requests (or zero if a limit field trial is | |
| 827 // active). | |
| 828 (scheduler_->limit_outstanding_requests() || | |
| 829 in_flight_delayable_count_ >= | |
| 830 max_num_delayable_while_layout_blocking_)) { | |
| 831 return DO_NOT_START_REQUEST_AND_STOP_SEARCHING; | |
| 832 } | |
| 795 } | 833 } |
| 796 | 834 |
| 797 return START_REQUEST; | 835 return START_REQUEST; |
| 798 } | 836 } |
| 799 | 837 |
| 800 void LoadAnyStartablePendingRequests() { | 838 void LoadAnyStartablePendingRequests() { |
| 801 // We iterate through all the pending requests, starting with the highest | 839 // We iterate through all the pending requests, starting with the highest |
| 802 // priority one. For each entry, one of three things can happen: | 840 // priority one. For each entry, one of three things can happen: |
| 803 // 1) We start the request, remove it from the list, and keep checking. | 841 // 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 | 842 // 2) We do NOT start the request, but ShouldStartRequest() signals us that |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 831 DCHECK(query_result == DO_NOT_START_REQUEST_AND_STOP_SEARCHING); | 869 DCHECK(query_result == DO_NOT_START_REQUEST_AND_STOP_SEARCHING); |
| 832 break; | 870 break; |
| 833 } | 871 } |
| 834 } | 872 } |
| 835 } | 873 } |
| 836 | 874 |
| 837 bool is_audible_; | 875 bool is_audible_; |
| 838 bool is_visible_; | 876 bool is_visible_; |
| 839 bool is_loaded_; | 877 bool is_loaded_; |
| 840 bool is_paused_; | 878 bool is_paused_; |
| 841 bool has_body_; | 879 // Tracks if the main HTML parser has reached the body which marks the end of |
| 880 // layout-blocking resources. | |
| 881 bool has_html_body_; | |
| 842 bool using_spdy_proxy_; | 882 bool using_spdy_proxy_; |
| 843 RequestQueue pending_requests_; | 883 RequestQueue pending_requests_; |
| 844 RequestSet in_flight_requests_; | 884 RequestSet in_flight_requests_; |
| 845 base::TimeTicks load_started_time_; | 885 base::TimeTicks load_started_time_; |
| 846 // The last time the client switched state between active and background. | 886 // The last time the client switched state between active and background. |
| 847 base::TimeTicks last_active_switch_time_; | 887 base::TimeTicks last_active_switch_time_; |
| 848 ResourceScheduler* scheduler_; | 888 ResourceScheduler* scheduler_; |
| 849 // The number of delayable in-flight requests. | 889 // The number of delayable in-flight requests. |
| 850 size_t in_flight_delayable_count_; | 890 size_t in_flight_delayable_count_; |
| 851 // The number of layout-blocking in-flight requests. | 891 // The number of layout-blocking in-flight requests. |
| 852 size_t total_layout_blocking_count_; | 892 size_t total_layout_blocking_count_; |
| 853 ResourceScheduler::ClientThrottleState throttle_state_; | 893 ResourceScheduler::ClientThrottleState throttle_state_; |
| 894 // Maximum number of delayable requests to allow at a time, regardless of | |
| 895 // the number of servers (limit to X concurrent requests across all hosts). | |
| 896 size_t max_num_delayable_requests_; | |
| 897 // Maximum number of delayable requests to allow while in the layout-blocking | |
| 898 // phase of resource loading. | |
| 899 size_t max_num_delayable_while_layout_blocking_; | |
| 900 // Determines if in_flight_layout_blocking_threshold_ should be used. | |
| 901 bool enable_layout_blocking_threshold_; | |
| 902 // Number number of non-delayable requests above which no delayable requests | |
| 903 // should be issued while in the layout-blocking phase of resource loading. | |
| 904 size_t in_flight_layout_blocking_threshold_; | |
| 905 // Priority level above which resources are considered layout-blocking and | |
| 906 // below which they are considered delayable. | |
| 907 net::RequestPriority layout_blocking_priority_threshold_; | |
| 854 }; | 908 }; |
| 855 | 909 |
| 856 ResourceScheduler::ResourceScheduler() | 910 ResourceScheduler::ResourceScheduler() |
| 857 : should_coalesce_(false), | 911 : should_coalesce_(false), |
| 858 should_throttle_(false), | 912 should_throttle_(false), |
| 859 active_clients_loading_(0), | 913 active_clients_loading_(0), |
| 860 coalesced_clients_(0), | 914 coalesced_clients_(0), |
| 861 limit_outstanding_requests_(false), | 915 limit_outstanding_requests_(false), |
| 862 outstanding_request_limit_(0), | 916 outstanding_request_limit_(0), |
| 917 layout_blocking_priority_threshold_( | |
| 918 kDefaultLayoutBlockingPriorityThreshold), | |
| 919 enable_layout_blocking_threshold_(false), | |
| 920 in_flight_layout_blocking_threshold_(0), | |
| 921 max_num_delayable_while_layout_blocking_( | |
| 922 kDefaultMaxNumDelayableWhileLayoutBlocking), | |
| 923 max_num_delayable_requests_(kDefaultMaxNumDelayableRequestsPerClient), | |
| 863 coalescing_timer_(new base::Timer(true /* retain_user_task */, | 924 coalescing_timer_(new base::Timer(true /* retain_user_task */, |
| 864 true /* is_repeating */)) { | 925 true /* is_repeating */)) { |
| 865 std::string throttling_trial_group = | 926 std::string throttling_trial_group = |
| 866 base::FieldTrialList::FindFullName(kThrottleCoalesceFieldTrial); | 927 base::FieldTrialList::FindFullName(kThrottleCoalesceFieldTrial); |
| 867 if (throttling_trial_group == kThrottleCoalesceFieldTrialThrottle) { | 928 if (throttling_trial_group == kThrottleCoalesceFieldTrialThrottle) { |
| 868 should_throttle_ = true; | 929 should_throttle_ = true; |
| 869 } else if (throttling_trial_group == kThrottleCoalesceFieldTrialCoalesce) { | 930 } else if (throttling_trial_group == kThrottleCoalesceFieldTrialCoalesce) { |
| 870 should_coalesce_ = true; | 931 should_coalesce_ = true; |
| 871 should_throttle_ = true; | 932 should_throttle_ = true; |
| 872 } | 933 } |
| 873 | 934 |
| 874 std::string outstanding_limit_trial_group = | 935 std::string outstanding_limit_trial_group = |
| 875 base::FieldTrialList::FindFullName(kRequestLimitFieldTrial); | 936 base::FieldTrialList::FindFullName(kRequestLimitFieldTrial); |
| 876 std::vector<std::string> split_group( | 937 std::vector<std::string> split_group( |
| 877 base::SplitString(outstanding_limit_trial_group, "=", | 938 base::SplitString(outstanding_limit_trial_group, "=", |
| 878 base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL)); | 939 base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL)); |
| 879 int outstanding_limit = 0; | 940 int outstanding_limit = 0; |
| 880 if (split_group.size() == 2 && | 941 if (split_group.size() == 2 && |
| 881 split_group[0] == kRequestLimitFieldTrialGroupPrefix && | 942 split_group[0] == kRequestLimitFieldTrialGroupPrefix && |
| 882 base::StringToInt(split_group[1], &outstanding_limit) && | 943 base::StringToInt(split_group[1], &outstanding_limit) && |
| 883 outstanding_limit > 0) { | 944 outstanding_limit > 0) { |
| 884 limit_outstanding_requests_ = true; | 945 limit_outstanding_requests_ = true; |
| 885 outstanding_request_limit_ = outstanding_limit; | 946 outstanding_request_limit_ = outstanding_limit; |
| 886 } | 947 } |
| 948 | |
| 949 // Set up the ResourceScheduling field trial options. | |
| 950 // The field trial parameters are also encoded into the group name since | |
| 951 // the variations component is not available from here and plumbing the | |
| 952 // options through the code is overkill for a short experiment. | |
| 953 // | |
| 954 // The group name encoding looks like this: | |
| 955 // <descriptiveName>_ABCDE_E2_F_G | |
| 956 // A - fetchDeferLateScripts (1 for true, 0 for false) | |
| 957 // B - fetchIncreaseFontPriority (1 for true, 0 for false) | |
| 958 // C - fetchIncreaseAsyncScriptPriority (1 for true, 0 for false) | |
| 959 // D - fetchIncreasePriorities (1 for true, 0 for false) | |
| 960 // E - fetchEnableLayoutBlockingThreshold (1 for true, 0 for false) | |
| 961 // E2 - fetchLayoutBlockingThreshold (Numeric) | |
| 962 // F - fetchMaxNumDelayableWhileLayoutBlocking (Numeric) | |
| 963 // G - fetchMaxNumDelayableRequests (Numeric) | |
| 964 std::string resource_priorities_trial_group = | |
| 965 base::FieldTrialList::FindFullName(kResourcePrioritiesFieldTrial); | |
| 966 std::vector<std::string> resource_priorities_split_group( | |
| 967 base::SplitString(resource_priorities_trial_group, "_", | |
| 968 base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL)); | |
| 969 if (resource_priorities_split_group.size() == 5 && | |
| 970 resource_priorities_split_group[1].length() == 5) { | |
| 971 // fetchIncreasePriorities | |
| 972 if (resource_priorities_split_group[1].at(3) == '1') | |
| 973 layout_blocking_priority_threshold_ = net::MEDIUM; | |
| 974 enable_layout_blocking_threshold_ = | |
| 975 resource_priorities_split_group[1].at(4) == '1'; | |
| 976 size_t numeric_value = 0; | |
| 977 if (base::StringToSizeT(resource_priorities_split_group[2], &numeric_value)) | |
| 978 in_flight_layout_blocking_threshold_ = numeric_value; | |
| 979 if (base::StringToSizeT(resource_priorities_split_group[3], &numeric_value)) | |
| 980 max_num_delayable_while_layout_blocking_ = numeric_value; | |
| 981 if (base::StringToSizeT(resource_priorities_split_group[4], &numeric_value)) | |
| 982 max_num_delayable_requests_ = numeric_value; | |
| 983 } | |
| 887 } | 984 } |
| 888 | 985 |
| 889 ResourceScheduler::~ResourceScheduler() { | 986 ResourceScheduler::~ResourceScheduler() { |
| 890 DCHECK(unowned_requests_.empty()); | 987 DCHECK(unowned_requests_.empty()); |
| 891 DCHECK(client_map_.empty()); | 988 DCHECK(client_map_.empty()); |
| 892 } | 989 } |
| 893 | 990 |
| 894 void ResourceScheduler::SetThrottleOptionsForTesting(bool should_throttle, | 991 void ResourceScheduler::SetThrottleOptionsForTesting(bool should_throttle, |
| 895 bool should_coalesce) { | 992 bool should_coalesce) { |
| 896 should_coalesce_ = should_coalesce; | 993 should_coalesce_ = should_coalesce; |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 950 } | 1047 } |
| 951 | 1048 |
| 952 void ResourceScheduler::OnClientCreated(int child_id, | 1049 void ResourceScheduler::OnClientCreated(int child_id, |
| 953 int route_id, | 1050 int route_id, |
| 954 bool is_visible, | 1051 bool is_visible, |
| 955 bool is_audible) { | 1052 bool is_audible) { |
| 956 DCHECK(CalledOnValidThread()); | 1053 DCHECK(CalledOnValidThread()); |
| 957 ClientId client_id = MakeClientId(child_id, route_id); | 1054 ClientId client_id = MakeClientId(child_id, route_id); |
| 958 DCHECK(!ContainsKey(client_map_, client_id)); | 1055 DCHECK(!ContainsKey(client_map_, client_id)); |
| 959 | 1056 |
| 960 Client* client = new Client(this, is_visible, is_audible); | 1057 Client* client = new Client(this, is_visible, is_audible, |
| 1058 layout_blocking_priority_threshold_, enable_layout_blocking_threshold_, | |
| 1059 in_flight_layout_blocking_threshold_, | |
| 1060 max_num_delayable_while_layout_blocking_, max_num_delayable_requests_); | |
| 961 client_map_[client_id] = client; | 1061 client_map_[client_id] = client; |
| 962 | 1062 |
| 963 client->UpdateThrottleState(); | 1063 client->UpdateThrottleState(); |
| 964 } | 1064 } |
| 965 | 1065 |
| 966 void ResourceScheduler::OnClientDeleted(int child_id, int route_id) { | 1066 void ResourceScheduler::OnClientDeleted(int child_id, int route_id) { |
| 967 DCHECK(CalledOnValidThread()); | 1067 DCHECK(CalledOnValidThread()); |
| 968 ClientId client_id = MakeClientId(child_id, route_id); | 1068 ClientId client_id = MakeClientId(child_id, route_id); |
| 969 DCHECK(ContainsKey(client_map_, client_id)); | 1069 DCHECK(ContainsKey(client_map_, client_id)); |
| 970 ClientMap::iterator it = client_map_.find(client_id); | 1070 ClientMap::iterator it = client_map_.find(client_id); |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1202 client->ReprioritizeRequest( | 1302 client->ReprioritizeRequest( |
| 1203 request, old_priority_params, new_priority_params); | 1303 request, old_priority_params, new_priority_params); |
| 1204 } | 1304 } |
| 1205 | 1305 |
| 1206 ResourceScheduler::ClientId ResourceScheduler::MakeClientId( | 1306 ResourceScheduler::ClientId ResourceScheduler::MakeClientId( |
| 1207 int child_id, int route_id) { | 1307 int child_id, int route_id) { |
| 1208 return (static_cast<ResourceScheduler::ClientId>(child_id) << 32) | route_id; | 1308 return (static_cast<ResourceScheduler::ClientId>(child_id) << 32) | route_id; |
| 1209 } | 1309 } |
| 1210 | 1310 |
| 1211 } // namespace content | 1311 } // namespace content |
| OLD | NEW |