Chromium Code Reviews| Index: content/browser/loader/resource_scheduler.cc |
| diff --git a/content/browser/loader/resource_scheduler.cc b/content/browser/loader/resource_scheduler.cc |
| index 1d118f0ffbc2ae3be243e75f8eb227a1073edfcf..82edd6f62a67fd0e80a6ac7792e8031be7389eb5 100644 |
| --- a/content/browser/loader/resource_scheduler.cc |
| +++ b/content/browser/loader/resource_scheduler.cc |
| @@ -4,8 +4,9 @@ |
| #include <set> |
| -#include "content/browser/loader/resource_scheduler.h" |
| - |
| +#include "base/base_switches.h" |
| +#include "base/basictypes.h" |
| +#include "base/command_line.h" |
| #include "base/metrics/field_trial.h" |
| #include "base/metrics/histogram.h" |
| #include "base/stl_util.h" |
| @@ -14,9 +15,11 @@ |
| #include "base/time/time.h" |
| #include "content/common/resource_messages.h" |
| #include "content/browser/loader/resource_message_delegate.h" |
| +#include "content/browser/loader/resource_scheduler.h" |
| #include "content/public/browser/resource_controller.h" |
| #include "content/public/browser/resource_request_info.h" |
| #include "content/public/browser/resource_throttle.h" |
| +#include "content/public/common/content_switches.h" |
| #include "ipc/ipc_message_macros.h" |
| #include "net/base/host_port_pair.h" |
| #include "net/base/load_flags.h" |
| @@ -303,7 +306,8 @@ class ResourceScheduler::Client { |
| public: |
| explicit Client(ResourceScheduler* scheduler, |
| bool is_visible, |
| - bool is_audible) |
| + bool is_audible, |
| + int fetch_mode) |
| : is_audible_(is_audible), |
| is_visible_(is_visible), |
| is_loaded_(false), |
| @@ -314,7 +318,8 @@ class ResourceScheduler::Client { |
| scheduler_(scheduler), |
| in_flight_delayable_count_(0), |
| total_layout_blocking_count_(0), |
| - throttle_state_(ResourceScheduler::THROTTLED) {} |
| + throttle_state_(ResourceScheduler::THROTTLED), |
| + fetch_mode_(fetch_mode) {} |
| ~Client() { |
| // Update to default state and pause to ensure the scheduler has a |
| @@ -624,22 +629,43 @@ class ResourceScheduler::Client { |
| RequestClassification ClassifyRequest(ScheduledResourceRequest* request) { |
| // If a request is already marked as layout-blocking make sure to keep the |
| // classification across redirects unless the priority was lowered. |
| - if (request->classification() == LAYOUT_BLOCKING_REQUEST && |
| - request->url_request()->priority() > net::LOW) { |
| - return LAYOUT_BLOCKING_REQUEST; |
| - } |
| + if (fetch_mode_ == 2) { |
| + if (request->classification() == LAYOUT_BLOCKING_REQUEST && |
| + request->url_request()->priority() > net::MEDIUM) { |
| + return LAYOUT_BLOCKING_REQUEST; |
| + } |
| - if (!has_body_ && request->url_request()->priority() > net::LOW) |
| - return LAYOUT_BLOCKING_REQUEST; |
| + if (!has_body_ && request->url_request()->priority() > net::MEDIUM) |
| + return LAYOUT_BLOCKING_REQUEST; |
| + |
| + if (request->url_request()->priority() < net::MEDIUM) { |
| + net::HostPortPair host_port_pair = |
| + net::HostPortPair::FromURL(request->url_request()->url()); |
| + net::HttpServerProperties& http_server_properties = |
| + *request->url_request()->context()->http_server_properties(); |
| + if (!http_server_properties.SupportsRequestPriority(host_port_pair) && |
| + ContainsKey(in_flight_requests_, request)) { |
| + return IN_FLIGHT_DELAYABLE_REQUEST; |
| + } |
| + } |
| + } else { |
| + if (request->classification() == LAYOUT_BLOCKING_REQUEST && |
| + request->url_request()->priority() > net::LOW) { |
| + return LAYOUT_BLOCKING_REQUEST; |
| + } |
| - if (request->url_request()->priority() < net::LOW) { |
| - net::HostPortPair host_port_pair = |
| - net::HostPortPair::FromURL(request->url_request()->url()); |
| - net::HttpServerProperties& http_server_properties = |
| - *request->url_request()->context()->http_server_properties(); |
| - if (!http_server_properties.SupportsRequestPriority(host_port_pair) && |
| - ContainsKey(in_flight_requests_, request)) { |
| - return IN_FLIGHT_DELAYABLE_REQUEST; |
| + if (!has_body_ && request->url_request()->priority() > net::LOW) |
| + return LAYOUT_BLOCKING_REQUEST; |
| + |
| + if (request->url_request()->priority() < net::LOW) { |
| + net::HostPortPair host_port_pair = |
| + net::HostPortPair::FromURL(request->url_request()->url()); |
| + net::HttpServerProperties& http_server_properties = |
| + *request->url_request()->context()->http_server_properties(); |
| + if (!http_server_properties.SupportsRequestPriority(host_port_pair) && |
| + ContainsKey(in_flight_requests_, request)) { |
| + return IN_FLIGHT_DELAYABLE_REQUEST; |
| + } |
| } |
| } |
| return NORMAL_REQUEST; |
| @@ -769,8 +795,14 @@ class ResourceScheduler::Client { |
| } |
| // High-priority and layout-blocking requests. |
| - if (url_request.priority() >= net::LOW) { |
| - return START_REQUEST; |
| + if (fetch_mode_ == 2) { |
| + if (url_request.priority() >= net::MEDIUM) { |
| + return START_REQUEST; |
| + } |
| + } else { |
| + if (url_request.priority() >= net::LOW) { |
| + return START_REQUEST; |
| + } |
| } |
| if (in_flight_delayable_count_ >= kMaxNumDelayableRequestsPerClient) { |
| @@ -783,15 +815,49 @@ class ResourceScheduler::Client { |
| return DO_NOT_START_REQUEST_AND_KEEP_SEARCHING; |
| } |
| - bool have_immediate_requests_in_flight = |
| - in_flight_requests_.size() > in_flight_delayable_count_; |
| - if (have_immediate_requests_in_flight && |
| - (!has_body_ || total_layout_blocking_count_ != 0) && |
| - // Do not allow a low priority request through in parallel if |
| - // we are in a limit field trial. |
| - (scheduler_->limit_outstanding_requests() || |
| - in_flight_delayable_count_ != 0)) { |
| - return DO_NOT_START_REQUEST_AND_STOP_SEARCHING; |
| + if (fetch_mode_ == 2) { |
| + // If we are in render-blocking more make sure at least 2 requests |
| + // are in-flight. High priority requests would have alreay |
| + // been allowed so this just restricts low-priority requests. |
| + if ((!has_body_ || total_layout_blocking_count_ != 0) && |
| + in_flight_requests_.size() >= 2) { |
|
Bryan McQuade
2015/07/29 17:53:47
it's hard for me to say with certainty that this i
Pat Meenan
2015/08/07 15:53:53
This has all been ripped out and replaced with fin
|
| + return DO_NOT_START_REQUEST_AND_STOP_SEARCHING; |
| + } |
| + |
| + // Allow 1 lower priority resource while 1 higher priority resource |
| + // is pending. If more than 1 higher priority resources are in flight |
| + // hold back from issuing any more lower priority requests. |
| + // This balances keeping the pipe from going idle when the last high |
| + // priority request completes but also limits the cases where low priority |
| + // requests will be contending with them for bandwidth. |
| + size_t higher_priority = 0; |
|
Bryan McQuade
2015/07/29 17:53:47
same as above (can we test this change separately
Pat Meenan
2015/08/07 15:53:53
Also replaced and finch-controllable now.
|
| + size_t equal_priority = 0; |
| + net::RequestPriority priority = url_request.priority(); |
| + for (RequestSet::const_iterator it = in_flight_requests_.begin(); |
| + it != in_flight_requests_.end(); ++it) { |
| + net::RequestPriority pending_priority = |
| + (*it)->get_request_priority_params().priority; |
| + if (pending_priority > priority) { |
| + higher_priority++; |
| + } else if (pending_priority == priority) { |
| + equal_priority++; |
| + } |
| + } |
| + if (higher_priority > 1 || (higher_priority == 1 && equal_priority > 0)) { |
| + return DO_NOT_START_REQUEST_AND_STOP_SEARCHING; |
| + } |
| + |
| + } else { |
| + bool have_immediate_requests_in_flight = |
| + in_flight_requests_.size() > in_flight_delayable_count_; |
| + if (have_immediate_requests_in_flight && |
| + (!has_body_ || total_layout_blocking_count_ != 0) && |
| + // Do not allow a low priority request through in parallel if |
| + // we are in a limit field trial. |
| + (scheduler_->limit_outstanding_requests() || |
| + in_flight_delayable_count_ != 0)) { |
| + return DO_NOT_START_REQUEST_AND_STOP_SEARCHING; |
| + } |
| } |
| return START_REQUEST; |
| @@ -851,6 +917,7 @@ class ResourceScheduler::Client { |
| // The number of layout-blocking in-flight requests. |
| size_t total_layout_blocking_count_; |
| ResourceScheduler::ClientThrottleState throttle_state_; |
| + int fetch_mode_; |
| }; |
| ResourceScheduler::ResourceScheduler() |
| @@ -860,6 +927,7 @@ ResourceScheduler::ResourceScheduler() |
| coalesced_clients_(0), |
| limit_outstanding_requests_(false), |
| outstanding_request_limit_(0), |
| + fetch_mode_(0), |
| coalescing_timer_(new base::Timer(true /* retain_user_task */, |
| true /* is_repeating */)) { |
| std::string throttling_trial_group = |
| @@ -884,6 +952,15 @@ ResourceScheduler::ResourceScheduler() |
| limit_outstanding_requests_ = true; |
| outstanding_request_limit_ = outstanding_limit; |
| } |
| + |
| + std::string fetch_mode_cmd = |
| + base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( |
| + switches::kFetchMode); |
| + if (!fetch_mode_cmd.empty()) { |
| + int temp; |
| + if (base::StringToInt(fetch_mode_cmd, &temp)) |
| + fetch_mode_ = temp; |
| + } |
| } |
| ResourceScheduler::~ResourceScheduler() { |
| @@ -957,7 +1034,7 @@ void ResourceScheduler::OnClientCreated(int child_id, |
| ClientId client_id = MakeClientId(child_id, route_id); |
| DCHECK(!ContainsKey(client_map_, client_id)); |
| - Client* client = new Client(this, is_visible, is_audible); |
| + Client* client = new Client(this, is_visible, is_audible, fetch_mode_); |
| client_map_[client_id] = client; |
| client->UpdateThrottleState(); |
| @@ -1187,6 +1264,10 @@ void ResourceScheduler::ReprioritizeRequest(ScheduledResourceRequest* request, |
| DCHECK(old_priority_params != new_priority_params); |
| + // only allow priority promotions |
| + if (fetch_mode_ == 2 && old_priority_params.GreaterThan(new_priority_params)) |
|
Bryan McQuade
2015/07/29 17:53:47
are there cases where we demote priorities today?
Pat Meenan
2015/08/07 15:53:53
I'll debug this case separately and not make it pa
|
| + return; |
| + |
| ClientMap::iterator client_it = client_map_.find(request->client_id()); |
| if (client_it == client_map_.end()) { |
| // The client was likely deleted shortly before we received this IPC. |