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

Unified Diff: content/browser/loader/resource_scheduler.cc

Issue 462813002: Changed resource scheduler to block until all critical resources actually load. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Cleaned up the request classification tracking logic Created 6 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « content/browser/loader/resource_scheduler.h ('k') | content/browser/loader/resource_scheduler_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: content/browser/loader/resource_scheduler.cc
diff --git a/content/browser/loader/resource_scheduler.cc b/content/browser/loader/resource_scheduler.cc
index 85adbdb30e275631b53af88286e75b658e73a16c..215ff6d16fe3929b641f513bfb38a2c34a89635f 100644
--- a/content/browser/loader/resource_scheduler.cc
+++ b/content/browser/loader/resource_scheduler.cc
@@ -128,7 +128,7 @@ class ResourceScheduler::ScheduledResourceRequest
scheduler_(scheduler),
priority_(priority),
fifo_ordering_(0),
- accounted_as_delayable_request_(false) {
+ classification_(NORMAL_REQUEST) {
TRACE_EVENT_ASYNC_BEGIN1("net", "URLRequest", request_,
"url", request->url().spec());
}
@@ -159,11 +159,11 @@ class ResourceScheduler::ScheduledResourceRequest
void set_fifo_ordering(uint32 fifo_ordering) {
fifo_ordering_ = fifo_ordering;
}
- bool accounted_as_delayable_request() const {
- return accounted_as_delayable_request_;
+ RequestClassification classification() const {
+ return classification_;
}
- void set_accounted_as_delayable_request(bool accounted) {
- accounted_as_delayable_request_ = accounted;
+ void set_classification(RequestClassification classification) {
+ classification_ = classification;
}
private:
@@ -195,11 +195,10 @@ class ResourceScheduler::ScheduledResourceRequest
net::URLRequest* request_;
bool ready_;
bool deferred_;
+ RequestClassification classification_;
ResourceScheduler* scheduler_;
RequestPriorityParams priority_;
uint32 fifo_ordering_;
- // True if the request is delayable in |in_flight_requests_|.
- bool accounted_as_delayable_request_;
DISALLOW_COPY_AND_ASSIGN(ScheduledResourceRequest);
};
@@ -237,7 +236,8 @@ class ResourceScheduler::Client {
is_paused_(false),
has_body_(false),
using_spdy_proxy_(false),
- total_delayable_count_(0),
+ in_flight_delayable_count_(0),
+ total_layout_blocking_count_(0),
throttle_state_(ResourceScheduler::THROTTLED) {
scheduler_ = scheduler;
}
@@ -254,11 +254,11 @@ class ResourceScheduler::Client {
void ScheduleRequest(
net::URLRequest* url_request,
ScheduledResourceRequest* request) {
- if (ShouldStartRequest(request) == START_REQUEST) {
+ if (ShouldStartRequest(request) == START_REQUEST)
StartRequest(request);
- } else {
+ else
pending_requests_.Insert(request);
- }
+ SetRequestClassification(request, GetRequestClassification(request));
}
void RemoveRequest(ScheduledResourceRequest* request) {
@@ -278,7 +278,7 @@ class ResourceScheduler::Client {
for (RequestSet::iterator it = in_flight_requests_.begin();
it != in_flight_requests_.end(); ++it) {
unowned_requests.insert(*it);
- (*it)->set_accounted_as_delayable_request(false);
+ (*it)->set_classification(NORMAL_REQUEST);
}
ClearInFlightRequests();
return unowned_requests;
@@ -374,7 +374,7 @@ class ResourceScheduler::Client {
DCHECK(ContainsKey(in_flight_requests_, request));
// The priority and SPDY support may have changed, so update the
// delayable count.
- SetRequestDelayable(request, IsDelayableRequest(request));
+ SetRequestClassification(request, GetRequestClassification(request));
// Request has already started.
return;
}
@@ -441,44 +441,90 @@ class ResourceScheduler::Client {
void InsertInFlightRequest(ScheduledResourceRequest* request) {
in_flight_requests_.insert(request);
- if (IsDelayableRequest(request))
- SetRequestDelayable(request, true);
+ SetRequestClassification(request, GetRequestClassification(request));
}
void EraseInFlightRequest(ScheduledResourceRequest* request) {
size_t erased = in_flight_requests_.erase(request);
DCHECK_EQ(1u, erased);
- SetRequestDelayable(request, false);
- DCHECK_LE(total_delayable_count_, in_flight_requests_.size());
+ // Clear any special state that we were tracking for this request.
+ SetRequestClassification(request, NORMAL_REQUEST);
}
void ClearInFlightRequests() {
in_flight_requests_.clear();
- total_delayable_count_ = 0;
+ in_flight_delayable_count_ = 0;
+ total_layout_blocking_count_ = 0;
+ }
+
+ size_t CountRequestsWithClassification(
+ const RequestClassification classification, const bool include_pending) {
+ size_t classification_request_count = 0;
+ for (RequestSet::const_iterator it = in_flight_requests_.begin();
+ it != in_flight_requests_.end(); ++it) {
+ if ((*it)->classification() == classification)
+ classification_request_count++;
+ }
+ if (include_pending) {
+ for (RequestQueue::NetQueue::const_iterator
+ it = pending_requests_.GetNextHighestIterator();
+ it != pending_requests_.End(); ++it) {
+ if ((*it)->classification() == classification)
+ classification_request_count++;
+ }
+ }
+ return classification_request_count;
+ }
+
+ void SetRequestClassification(ScheduledResourceRequest* request,
+ RequestClassification classification) {
+ RequestClassification old_classification = request->classification();
+ if (old_classification == classification)
+ return;
+
+ bool in_flight = !pending_requests_.IsQueued(request);
mmenke 2014/08/18 20:59:43 This isn't used.
Pat Meenan 2014/08/20 14:57:31 Done.
+
+ if (old_classification == IN_FLIGHT_DELAYABLE_REQUEST)
+ in_flight_delayable_count_--;
+ if (old_classification == LAYOUT_BLOCKING_REQUEST)
+ total_layout_blocking_count_--;
+
+ if (classification == IN_FLIGHT_DELAYABLE_REQUEST)
+ in_flight_delayable_count_++;
+ if (classification == LAYOUT_BLOCKING_REQUEST)
+ total_layout_blocking_count_++;
+
+ request->set_classification(classification);
+ DCHECK_EQ(
+ CountRequestsWithClassification(IN_FLIGHT_DELAYABLE_REQUEST, false),
+ in_flight_delayable_count_);
+ DCHECK_EQ(CountRequestsWithClassification(LAYOUT_BLOCKING_REQUEST, true),
+ total_layout_blocking_count_);
}
- bool IsDelayableRequest(ScheduledResourceRequest* request) {
+ RequestClassification GetRequestClassification(
mmenke 2014/08/18 20:59:43 Still think we should reconsider this name, to mak
Pat Meenan 2014/08/20 14:57:32 Done. Changed it to ClassifyRequest() which better
+ 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 (!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.SupportsSpdy(host_port_pair)) {
- return true;
+ if (!http_server_properties.SupportsSpdy(host_port_pair) &&
+ !pending_requests_.IsQueued(request)) {
mmenke 2014/08/18 20:59:42 Can we check in_flight_requests_ instead? Seems w
Pat Meenan 2014/08/20 14:57:32 Done.
+ return IN_FLIGHT_DELAYABLE_REQUEST;
}
}
- return false;
- }
-
- void SetRequestDelayable(ScheduledResourceRequest* request,
- bool delayable) {
- if (request->accounted_as_delayable_request() == delayable)
- return;
- if (delayable)
- total_delayable_count_++;
- else
- total_delayable_count_--;
- request->set_accounted_as_delayable_request(delayable);
+ return NORMAL_REQUEST;
}
bool ShouldKeepSearching(
@@ -504,7 +550,7 @@ class ResourceScheduler::Client {
// ShouldStartRequest is the main scheduling algorithm.
//
- // Requests are categorized into three categories:
+ // Requests are evaluated on five attributes:
//
// 1. Non-delayable requests:
// * Synchronous requests.
@@ -515,20 +561,23 @@ class ResourceScheduler::Client {
// 3. High-priority requests:
// * Higher priority requests (>= net::LOW).
//
- // 4. Low priority requests
+ // 4. Layout-blocking requests:
+ // * High-priority requests initiated before the renderer has a <body>.
+ //
+ // 5. Low priority requests
//
// The following rules are followed:
//
// ACTIVE_AND_LOADING and UNTHROTTLED Clients follow these rules:
- // * Non-delayable, High-priority and SDPY capable requests are issued
- // immediately
- // * If no high priority requests are in flight, start loading low priority
- // requests.
+ // * Non-delayable, High-priority and SPDY capable requests are issued
+ // immediately.
// * Low priority requests are delayable.
- // * Once the renderer has a <body>, start loading delayable requests.
+ // * Allow one delayable request to load at a time while layout-blocking
+ // requests are loading.
+ // * If no high priority or layout-blocking requests are in flight, start
+ // loading delayable requests.
// * Never exceed 10 delayable requests in flight per client.
// * Never exceed 6 delayable requests for a given host.
- // * Prior to <body>, allow one delayable request to load at a time.
//
// THROTTLED Clients follow these rules:
// * Non-delayable and SPDY-capable requests are issued immediately.
@@ -585,12 +634,12 @@ class ResourceScheduler::Client {
return DO_NOT_START_REQUEST_AND_KEEP_SEARCHING;
}
+ // High-priority and layout-blocking requests.
if (url_request.priority() >= net::LOW) {
return START_REQUEST;
}
- size_t num_delayable_requests_in_flight = total_delayable_count_;
- if (num_delayable_requests_in_flight >= kMaxNumDelayableRequestsPerClient) {
+ if (in_flight_delayable_count_ >= kMaxNumDelayableRequestsPerClient) {
return DO_NOT_START_REQUEST_AND_STOP_SEARCHING;
}
@@ -601,9 +650,10 @@ class ResourceScheduler::Client {
}
bool have_immediate_requests_in_flight =
- in_flight_requests_.size() > num_delayable_requests_in_flight;
- if (have_immediate_requests_in_flight && !has_body_ &&
- num_delayable_requests_in_flight != 0) {
+ in_flight_requests_.size() > in_flight_delayable_count_;
+ if (have_immediate_requests_in_flight &&
+ total_layout_blocking_count_ != 0 &&
+ in_flight_delayable_count_ != 0) {
return DO_NOT_START_REQUEST_AND_STOP_SEARCHING;
}
@@ -657,7 +707,9 @@ class ResourceScheduler::Client {
RequestSet in_flight_requests_;
ResourceScheduler* scheduler_;
// The number of delayable in-flight requests.
- size_t total_delayable_count_;
+ size_t in_flight_delayable_count_;
+ // The number of layout-blocking in-flight requests.
+ size_t total_layout_blocking_count_;
ResourceScheduler::ClientThrottleState throttle_state_;
};
« no previous file with comments | « content/browser/loader/resource_scheduler.h ('k') | content/browser/loader/resource_scheduler_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698