 Chromium Code Reviews
 Chromium Code Reviews Issue 393163003:
  Add coalescing timer to ResourceScheduler. CL 2 from BUG=128035.  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@rsblank
    
  
    Issue 393163003:
  Add coalescing timer to ResourceScheduler. CL 2 from BUG=128035.  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@rsblank| 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" | 
| 11 #include "content/browser/loader/resource_message_delegate.h" | 11 #include "content/browser/loader/resource_message_delegate.h" | 
| 12 #include "content/public/browser/resource_controller.h" | 12 #include "content/public/browser/resource_controller.h" | 
| 13 #include "content/public/browser/resource_request_info.h" | 13 #include "content/public/browser/resource_request_info.h" | 
| 14 #include "content/public/browser/resource_throttle.h" | 14 #include "content/public/browser/resource_throttle.h" | 
| 15 #include "ipc/ipc_message_macros.h" | 15 #include "ipc/ipc_message_macros.h" | 
| 16 #include "net/base/host_port_pair.h" | 16 #include "net/base/host_port_pair.h" | 
| 17 #include "net/base/load_flags.h" | 17 #include "net/base/load_flags.h" | 
| 18 #include "net/base/request_priority.h" | 18 #include "net/base/request_priority.h" | 
| 19 #include "net/http/http_server_properties.h" | 19 #include "net/http/http_server_properties.h" | 
| 20 #include "net/url_request/url_request.h" | 20 #include "net/url_request/url_request.h" | 
| 21 #include "net/url_request/url_request_context.h" | 21 #include "net/url_request/url_request_context.h" | 
| 22 | 22 | 
| 23 namespace content { | 23 namespace content { | 
| 24 | 24 | 
| 25 static const size_t kCoalescedTimerPeriod = 5000; | |
| 25 static const size_t kMaxNumDelayableRequestsPerClient = 10; | 26 static const size_t kMaxNumDelayableRequestsPerClient = 10; | 
| 26 static const size_t kMaxNumDelayableRequestsPerHost = 6; | 27 static const size_t kMaxNumDelayableRequestsPerHost = 6; | 
| 27 static const size_t kMaxNumThrottledRequestsPerClient = 1; | 28 static const size_t kMaxNumThrottledRequestsPerClient = 1; | 
| 28 | 29 | 
| 29 struct ResourceScheduler::RequestPriorityParams { | 30 struct ResourceScheduler::RequestPriorityParams { | 
| 30 RequestPriorityParams() | 31 RequestPriorityParams() | 
| 31 : priority(net::DEFAULT_PRIORITY), | 32 : priority(net::DEFAULT_PRIORITY), | 
| 32 intra_priority(0) { | 33 intra_priority(0) { | 
| 33 } | 34 } | 
| 34 | 35 | 
| (...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 308 SetThrottleState(ACTIVE_AND_LOADING); | 309 SetThrottleState(ACTIVE_AND_LOADING); | 
| 309 } else if (is_active()) { | 310 } else if (is_active()) { | 
| 310 SetThrottleState(UNTHROTTLED); | 311 SetThrottleState(UNTHROTTLED); | 
| 311 } else if (!scheduler_->active_clients_loaded()) { | 312 } else if (!scheduler_->active_clients_loaded()) { | 
| 312 SetThrottleState(THROTTLED); | 313 SetThrottleState(THROTTLED); | 
| 313 } else if (is_loaded_ && scheduler_->should_coalesce()) { | 314 } else if (is_loaded_ && scheduler_->should_coalesce()) { | 
| 314 SetThrottleState(COALESCED); | 315 SetThrottleState(COALESCED); | 
| 315 } else if (!is_active()) { | 316 } else if (!is_active()) { | 
| 316 SetThrottleState(UNTHROTTLED); | 317 SetThrottleState(UNTHROTTLED); | 
| 317 } | 318 } | 
| 319 | |
| 318 if (throttle_state_ == old_throttle_state) { | 320 if (throttle_state_ == old_throttle_state) { | 
| 319 return; | 321 return; | 
| 320 } | 322 } | 
| 321 if (throttle_state_ == ACTIVE_AND_LOADING) { | 323 if (throttle_state_ == ACTIVE_AND_LOADING) { | 
| 322 scheduler_->IncrementActiveClientsLoading(); | 324 scheduler_->IncrementActiveClientsLoading(); | 
| 323 } else if (old_throttle_state == ACTIVE_AND_LOADING) { | 325 } else if (old_throttle_state == ACTIVE_AND_LOADING) { | 
| 324 scheduler_->DecrementActiveClientsLoading(); | 326 scheduler_->DecrementActiveClientsLoading(); | 
| 325 } | 327 } | 
| 328 if (throttle_state_ == COALESCED) { | |
| 329 scheduler_->IncrementCoalescedClients(); | |
| 330 } else if (old_throttle_state == COALESCED) { | |
| 331 scheduler_->DecrementCoalescedClients(); | |
| 332 } | |
| 
aiolos (Not reviewing)
2014/07/15 23:54:58
We don't need to have the timer running when we do
 
mmenke
2014/07/16 17:01:34
We could be even more careful with this - if no co
 | |
| 326 } | 333 } | 
| 327 | 334 | 
| 328 void OnNavigate() { | 335 void OnNavigate() { | 
| 329 has_body_ = false; | 336 has_body_ = false; | 
| 330 is_loaded_ = false; | 337 is_loaded_ = false; | 
| 331 } | 338 } | 
| 332 | 339 | 
| 333 void OnWillInsertBody() { | 340 void OnWillInsertBody() { | 
| 334 has_body_ = true; | 341 has_body_ = true; | 
| 335 LoadAnyStartablePendingRequests(); | 342 LoadAnyStartablePendingRequests(); | 
| (...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 627 bool has_body_; | 634 bool has_body_; | 
| 628 bool using_spdy_proxy_; | 635 bool using_spdy_proxy_; | 
| 629 RequestQueue pending_requests_; | 636 RequestQueue pending_requests_; | 
| 630 RequestSet in_flight_requests_; | 637 RequestSet in_flight_requests_; | 
| 631 ResourceScheduler* scheduler_; | 638 ResourceScheduler* scheduler_; | 
| 632 // The number of delayable in-flight requests. | 639 // The number of delayable in-flight requests. | 
| 633 size_t total_delayable_count_; | 640 size_t total_delayable_count_; | 
| 634 ResourceScheduler::ClientThrottleState throttle_state_; | 641 ResourceScheduler::ClientThrottleState throttle_state_; | 
| 635 }; | 642 }; | 
| 636 | 643 | 
| 637 ResourceScheduler::ResourceScheduler() : active_clients_loading_(0) { | 644 ResourceScheduler::ResourceScheduler() | 
| 645 : active_clients_loading_(0), | |
| 646 coalesced_clients_(0), | |
| 647 coalescing_timer_(new base::Timer(true, true)) { | |
| 
mmenke
2014/07/16 17:01:34
Suggest labelling the two arguments, like:
new ba
 | |
| 638 } | 648 } | 
| 639 | 649 | 
| 640 ResourceScheduler::~ResourceScheduler() { | 650 ResourceScheduler::~ResourceScheduler() { | 
| 641 DCHECK(unowned_requests_.empty()); | 651 DCHECK(unowned_requests_.empty()); | 
| 642 DCHECK(client_map_.empty()); | 652 DCHECK(client_map_.empty()); | 
| 643 } | 653 } | 
| 644 | 654 | 
| 645 void ResourceScheduler::SetThrottleOptionsForTesting(bool should_throttle, | 655 void ResourceScheduler::SetThrottleOptionsForTesting(bool should_throttle, | 
| 646 bool should_coalesce) { | 656 bool should_coalesce) { | 
| 647 should_coalesce_ = should_coalesce; | 657 should_coalesce_ = should_coalesce; | 
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 843 while (client_it != client_map_.end()) { | 853 while (client_it != client_map_.end()) { | 
| 844 Client* client = client_it->second; | 854 Client* client = client_it->second; | 
| 845 if (client->throttle_state() == ACTIVE_AND_LOADING) { | 855 if (client->throttle_state() == ACTIVE_AND_LOADING) { | 
| 846 ++active_and_loading; | 856 ++active_and_loading; | 
| 847 } | 857 } | 
| 848 ++client_it; | 858 ++client_it; | 
| 849 } | 859 } | 
| 850 return active_and_loading; | 860 return active_and_loading; | 
| 851 } | 861 } | 
| 852 | 862 | 
| 863 void ResourceScheduler::IncrementCoalescedClients() { | |
| 
aiolos (Not reviewing)
2014/07/15 23:54:58
I wondered about adding tests to check that the ti
 
mmenke
2014/07/16 17:01:34
It is a bit of a transparent implementation detail
 | |
| 864 ++coalesced_clients_; | |
| 865 DCHECK_EQ(coalesced_clients_, CountCoalescedClients()); | |
| 866 if (coalesced_clients_ == 1) { | |
| 867 coalescing_timer_->Start( | |
| 868 FROM_HERE, | |
| 869 base::TimeDelta::FromMilliseconds(kCoalescedTimerPeriod), | |
| 870 base::Bind(&ResourceScheduler::LoadCoalescedRequests, | |
| 871 base::Unretained(this))); | |
| 872 } | |
| 873 } | |
| 874 | |
| 875 void ResourceScheduler::DecrementCoalescedClients() { | |
| 876 DCHECK_NE(0U, coalesced_clients_); | |
| 877 --coalesced_clients_; | |
| 878 DCHECK_EQ(coalesced_clients_, CountCoalescedClients()); | |
| 879 if (coalesced_clients_ == 0) { | |
| 880 coalescing_timer_->Stop(); | |
| 881 } | |
| 882 } | |
| 883 | |
| 884 size_t ResourceScheduler::CountCoalescedClients() { | |
| 
mmenke
2014/07/16 17:01:33
nit:  This should be const (As should CountActiveC
 | |
| 885 size_t coalesced_clients = 0; | |
| 886 ClientMap::iterator client_it = client_map_.begin(); | |
| 887 while (client_it != client_map_.end()) { | |
| 888 Client* client = client_it->second; | |
| 889 if (client->throttle_state() == COALESCED) { | |
| 890 ++coalesced_clients; | |
| 891 } | |
| 892 ++client_it; | |
| 893 } | |
| 894 return coalesced_clients_; | |
| 895 } | |
| 896 | |
| 897 void ResourceScheduler::LoadCoalescedRequests() { | |
| 
mmenke
2014/07/16 17:01:34
nit:  Should use a similar naming scheme here as i
 
aiolos (Not reviewing)
2014/07/24 17:09:54
The code structures are parallel, but when/why the
 | |
| 898 ClientMap::iterator client_it = client_map_.begin(); | |
| 899 while (client_it != client_map_.end()) { | |
| 900 Client* client = client_it->second; | |
| 901 client->LoadCoalescedRequests(); | |
| 902 ++client_it; | |
| 903 } | |
| 904 } | |
| 905 | |
| 853 void ResourceScheduler::ReprioritizeRequest(ScheduledResourceRequest* request, | 906 void ResourceScheduler::ReprioritizeRequest(ScheduledResourceRequest* request, | 
| 854 net::RequestPriority new_priority, | 907 net::RequestPriority new_priority, | 
| 855 int new_intra_priority_value) { | 908 int new_intra_priority_value) { | 
| 856 if (request->url_request()->load_flags() & net::LOAD_IGNORE_LIMITS) { | 909 if (request->url_request()->load_flags() & net::LOAD_IGNORE_LIMITS) { | 
| 857 // We should not be re-prioritizing requests with the | 910 // We should not be re-prioritizing requests with the | 
| 858 // IGNORE_LIMITS flag. | 911 // IGNORE_LIMITS flag. | 
| 859 NOTREACHED(); | 912 NOTREACHED(); | 
| 860 return; | 913 return; | 
| 861 } | 914 } | 
| 862 RequestPriorityParams new_priority_params(new_priority, | 915 RequestPriorityParams new_priority_params(new_priority, | 
| (...skipping 18 matching lines...) Expand all Loading... | |
| 881 client->ReprioritizeRequest( | 934 client->ReprioritizeRequest( | 
| 882 request, old_priority_params, new_priority_params); | 935 request, old_priority_params, new_priority_params); | 
| 883 } | 936 } | 
| 884 | 937 | 
| 885 ResourceScheduler::ClientId ResourceScheduler::MakeClientId( | 938 ResourceScheduler::ClientId ResourceScheduler::MakeClientId( | 
| 886 int child_id, int route_id) { | 939 int child_id, int route_id) { | 
| 887 return (static_cast<ResourceScheduler::ClientId>(child_id) << 32) | route_id; | 940 return (static_cast<ResourceScheduler::ClientId>(child_id) << 32) | route_id; | 
| 888 } | 941 } | 
| 889 | 942 | 
| 890 } // namespace content | 943 } // namespace content | 
| OLD | NEW |