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..8e8feb5f7773307eb83e0806ae541f50e5e9b32a 100644 |
| --- a/content/browser/loader/resource_scheduler.cc |
| +++ b/content/browser/loader/resource_scheduler.cc |
| @@ -6,6 +6,9 @@ |
| #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" |
| @@ -17,6 +20,7 @@ |
| #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" |
| @@ -314,7 +318,17 @@ 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_(0) { |
| + std::string fetch_mode_cmd = |
|
Bryan McQuade
2015/07/22 17:46:48
Could we make ResourceScheduler constructor the ca
Pat Meenan
2015/07/28 17:14:21
Done.
|
| + base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( |
| + switches::kFetchMode); |
| + if (!fetch_mode_cmd.empty()) { |
| + int temp; |
| + if (base::StringToInt(fetch_mode_cmd, &temp)) |
| + fetch_mode_ = temp; |
| + } |
| + } |
| ~Client() { |
| // Update to default state and pause to ensure the scheduler has a |
| @@ -328,6 +342,11 @@ class ResourceScheduler::Client { |
| void ScheduleRequest( |
| net::URLRequest* url_request, |
| ScheduledResourceRequest* request) { |
| +/* |
| + char buff[20]; |
| + wsprintfA(buff, "[%d] - ", request->get_request_priority_params().priority); |
| + OutputDebugStringA(std::string(std::string(buff) + request->url_request()->url().spec()).c_str()); |
| +*/ |
| if (ShouldStartRequest(request) == START_REQUEST) |
| StartRequest(request); |
| else |
| @@ -475,6 +494,7 @@ class ResourceScheduler::Client { |
| } |
| void OnWillInsertBody() { |
| +// OutputDebugStringA("************ Inserted Body"); |
| has_body_ = true; |
| LoadAnyStartablePendingRequests(); |
| } |
| @@ -491,6 +511,11 @@ class ResourceScheduler::Client { |
| RequestPriorityParams new_priority_params) { |
| request->url_request()->SetPriority(new_priority_params.priority); |
| request->set_request_priority_params(new_priority_params); |
| +/* |
| + char buff[30]; |
| + wsprintfA(buff, "[%d -> %d] - ", old_priority_params.priority, new_priority_params.priority); |
| + OutputDebugStringA(std::string(std::string(buff) + request->url_request()->url().spec()).c_str()); |
| +*/ |
| if (!pending_requests_.IsQueued(request)) { |
| DCHECK(ContainsKey(in_flight_requests_, request)); |
| // The priority of the request and priority support of the server may |
| @@ -624,22 +649,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; |
| @@ -663,6 +709,21 @@ class ResourceScheduler::Client { |
| void StartRequest(ScheduledResourceRequest* request) { |
| InsertInFlightRequest(request); |
| +/* |
| + size_t counts[5]; |
| + memset(&counts, 0, sizeof(counts)); |
| + // count the in-flight requests at each priority level |
| + for (RequestSet::const_iterator it = in_flight_requests_.begin(); |
| + it != in_flight_requests_.end(); ++it) { |
| + int priority = (*it)->get_request_priority_params().priority; |
| + if (priority >= 0 && priority <= 4) { |
| + counts[priority]++; |
| + } |
| + } |
| + char buff[80]; |
| + wsprintfA(buff, "Starting [%d] - %s{%d:%d:%d:%d:%d}%s - ", request->get_request_priority_params().priority, has_body_ ? "" : "*", counts[0], counts[1], counts[2], counts[3], counts[4], has_body_ ? "" : "*"); |
| + OutputDebugStringA(std::string(std::string(buff) + request->url_request()->url().spec()).c_str()); |
| +*/ |
| request->Start(); |
| } |
| @@ -769,8 +830,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 +850,43 @@ 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) { |
| + return DO_NOT_START_REQUEST_AND_STOP_SEARCHING; |
| + } |
| + |
| + // only allow 1 lower priority resource while 1 higher priority resource is pending |
| + size_t higher_priority = 0; |
| + 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 +946,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 +956,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 +981,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() { |
| @@ -1187,6 +1293,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)) |
| + 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. |