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. |