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

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

Issue 1230133005: Fix Resource Priorities and Scheduling (Chrome Side) (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Updated comment 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 "content/browser/loader/resource_scheduler.h"
mmenke 2015/08/11 17:57:23 Add blank line after this include.
Pat Meenan 2015/08/12 16:20:59 Done.
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
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
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
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)
mmenke 2015/08/11 17:57:23 I was actually thinking these could all be grabbed
Pat Meenan 2015/08/12 16:20:59 Done.
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
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
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
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_) {
mmenke 2015/08/11 17:57:23 While we're here, is the second condition really n
Pat Meenan 2015/08/12 16:20:59 Done.
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;
mmenke 2015/08/11 17:57:23 Having our enum names depend on deducing informati
Pat Meenan 2015/08/12 16:20:59 It's a bit more complicated because there's also s
mmenke 2015/08/12 16:31:06 Talking on another thread about getting this infor
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;
mmenke 2015/08/11 17:57:23 I don't think the SPDY change belongs in this CL.
Pat Meenan 2015/08/12 16:21:00 Agreed. We'll address this separately because the
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 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
738 if (throttle_state_ == COALESCED) { 755 if (throttle_state_ == COALESCED) {
739 return DO_NOT_START_REQUEST_AND_STOP_SEARCHING; 756 return DO_NOT_START_REQUEST_AND_STOP_SEARCHING;
740 } 757 }
741 758
742 if (using_spdy_proxy_ && url_request.url().SchemeIs(url::kHttpScheme)) { 759 if (using_spdy_proxy_ && url_request.url().SchemeIs(url::kHttpScheme)) {
743 return START_REQUEST; 760 return START_REQUEST;
744 } 761 }
745 762
746 // Implementation of the kRequestLimitFieldTrial. 763 // Implementation of the kRequestLimitFieldTrial.
747 if (scheduler_->limit_outstanding_requests() && 764 if (scheduler_->limit_outstanding_requests() &&
748 in_flight_requests_.size() >= scheduler_->outstanding_request_limit()) { 765 in_flight_requests_.size() >= scheduler_->outstanding_request_limit()) {
mmenke 2015/08/11 17:57:23 Note that you may run into this experiment, which
Pat Meenan 2015/08/12 16:20:59 Acknowledged.
749 return DO_NOT_START_REQUEST_AND_STOP_SEARCHING; 766 return DO_NOT_START_REQUEST_AND_STOP_SEARCHING;
750 } 767 }
751 768
752 net::HostPortPair host_port_pair = 769 net::HostPortPair host_port_pair =
753 net::HostPortPair::FromURL(url_request.url()); 770 net::HostPortPair::FromURL(url_request.url());
754 net::HttpServerProperties& http_server_properties = 771 net::HttpServerProperties& http_server_properties =
755 *url_request.context()->http_server_properties(); 772 *url_request.context()->http_server_properties();
756 773
757 // TODO(willchan): We should really improve this algorithm as described in 774 // TODO(willchan): We should really improve this algorithm as described in
758 // crbug.com/164101. Also, theoretically we should not count a 775 // crbug.com/164101. Also, theoretically we should not count a
759 // request-priority capable request against the delayable requests limit. 776 // request-priority capable request against the delayable requests limit.
760 if (http_server_properties.SupportsRequestPriority(host_port_pair)) { 777 if (http_server_properties.SupportsRequestPriority(host_port_pair)) {
761 return START_REQUEST; 778 return START_REQUEST;
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_) {
mmenke 2015/08/11 17:57:23 This is kinda weird...We're looking at the layout
Pat Meenan 2015/08/12 16:21:00 I can rename this if we come to a decision on what
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_;
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
mmenke 2015/08/11 17:57:23 This should probably say "block the request if..."
Pat Meenan 2015/08/12 16:20:59 Done.
816 // concurrent lower priority requests has not been hit.
mmenke 2015/08/11 17:57:23 This should either before the if, or inside the if
Pat Meenan 2015/08/12 16:20:59 Done.
817 (scheduler_->limit_outstanding_requests() ||
818 in_flight_delayable_count_ >=
819 max_num_delayable_while_layout_blocking_)) {
mmenke 2015/08/11 19:27:28 max_num_delayable_while_layout_blocking_ is used w
Pat Meenan 2015/08/12 16:20:59 They have slightly different behaviors which is wh
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).
mmenke 2015/08/11 17:57:23 Again, this should either before the if, or inside
Pat Meenan 2015/08/12 16:20:59 Done.
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
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)
mmenke 2015/08/11 19:27:28 I suggest an underscore between D and E, to separa
Pat Meenan 2015/08/12 16:20:59 Though D is also a special case because it affects
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698