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

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

Issue 146333004: Introduce an intra-priority level sorting value - Chromium Side (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Upload again. Created 6 years, 10 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 15c70270033dc8dbf563752b7aa50be12496b047..09dc06243911e9951422a3e3fe0f3cd0fbe0dae7 100644
--- a/content/browser/loader/resource_scheduler.cc
+++ b/content/browser/loader/resource_scheduler.cc
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <set>
+
#include "content/browser/loader/resource_scheduler.h"
#include "base/stl_util.h"
@@ -23,54 +25,49 @@ namespace content {
static const size_t kMaxNumDelayableRequestsPerClient = 10;
static const size_t kMaxNumDelayableRequestsPerHost = 6;
-// A thin wrapper around net::PriorityQueue that deals with
-// ScheduledResourceRequests instead of PriorityQueue::Pointers.
-class ResourceScheduler::RequestQueue {
- private:
- typedef net::PriorityQueue<ScheduledResourceRequest*> NetQueue;
- public:
- class Iterator {
- public:
- Iterator(NetQueue* queue) : queue_(queue) {
- DCHECK(queue != NULL);
- current_pointer_ = queue_->FirstMax();
- }
+struct ResourceScheduler::RequestPriorityParams {
+ RequestPriorityParams()
+ : priority(net::DEFAULT_PRIORITY),
+ intra_priority(0)
darin (slow to review) 2014/03/24 18:23:33 nit: opening "{" on previous line
shatch 2014/03/24 21:08:44 Done.
+ {
+ }
- Iterator& operator++() {
- current_pointer_ = queue_->GetNextTowardsLastMin(current_pointer_);
- return *this;
- }
+ RequestPriorityParams(net::RequestPriority priority, int intra_priority)
+ : priority(priority),
+ intra_priority(intra_priority) {
+ }
- Iterator operator++(int) {
- Iterator result(*this);
- ++(*this);
- return result;
- }
+ bool operator==(const RequestPriorityParams& other) const {
+ return (priority == other.priority) &&
+ (intra_priority == other.intra_priority);
+ }
- ScheduledResourceRequest* value() {
- return current_pointer_.value();
- }
+ bool operator!=(const RequestPriorityParams& other) const {
+ return (priority != other.priority) ||
darin (slow to review) 2014/03/24 18:23:33 nit: Implement in terms of operator== ? e.g.: ret
shatch 2014/03/24 21:08:44 Done.
+ (intra_priority != other.intra_priority);
+ }
- bool is_null() {
- return current_pointer_.is_null();
- }
+ bool GetSortingValue(const RequestPriorityParams& other) const {
darin (slow to review) 2014/03/24 18:23:33 nit: maybe call this function GreaterThan (or inve
shatch 2014/03/24 21:08:44 Done.
+ if (priority != other.priority)
+ return priority > other.priority;
+ return intra_priority > other.intra_priority;
+ }
- private:
- NetQueue* queue_;
- NetQueue::Pointer current_pointer_;
- };
+ net::RequestPriority priority;
+ int intra_priority;
+};
+
+class ResourceScheduler::RequestQueue {
+ public:
+ typedef std::multiset<ScheduledResourceRequest*, ScheduledResourceSorter>
+ NetQueue;
- RequestQueue() : queue_(net::NUM_PRIORITIES) {}
+ RequestQueue() : fifo_ordering_ids_(0) {}
~RequestQueue() {}
// Adds |request| to the queue with given |priority|.
- void Insert(ScheduledResourceRequest* request,
- net::RequestPriority priority) {
- DCHECK(!ContainsKey(pointers_, request));
- NetQueue::Pointer pointer = queue_.Insert(request, priority);
- pointers_[request] = pointer;
- }
+ void Insert(ScheduledResourceRequest* request);
// Removes |request| from the queue.
void Erase(ScheduledResourceRequest* request) {
@@ -78,17 +75,16 @@ class ResourceScheduler::RequestQueue {
DCHECK(it != pointers_.end());
if (it == pointers_.end())
return;
- queue_.Erase(it->second);
+ queue_.erase(it->second);
pointers_.erase(it);
}
- // Returns the highest priority request that's queued, or NULL if none are.
- ScheduledResourceRequest* FirstMax() {
- return queue_.FirstMax().value();
+ NetQueue::iterator GetNextHighestIterator() {
+ return queue_.begin();
}
- Iterator GetNextHighestIterator() {
- return Iterator(&queue_);
+ NetQueue::iterator End() {
+ return queue_.end();
}
// Returns true if |request| is queued.
@@ -100,7 +96,16 @@ class ResourceScheduler::RequestQueue {
bool IsEmpty() const { return queue_.size() == 0; }
private:
- typedef std::map<ScheduledResourceRequest*, NetQueue::Pointer> PointerMap;
+ typedef std::map<ScheduledResourceRequest*, NetQueue::iterator> PointerMap;
+
+ uint32 MakeFifoOrderingId() {
+ fifo_ordering_ids_ += 1;
+ return fifo_ordering_ids_;
+ }
+
+ // Used to create an ordering ID for scheduled resources so that resources
+ // with same priority/intra_priority stay in fifo order.
+ uint32 fifo_ordering_ids_;
NetQueue queue_;
PointerMap pointers_;
@@ -114,13 +119,16 @@ class ResourceScheduler::ScheduledResourceRequest
public:
ScheduledResourceRequest(const ClientId& client_id,
net::URLRequest* request,
- ResourceScheduler* scheduler)
+ ResourceScheduler* scheduler,
+ const RequestPriorityParams& priority)
: ResourceMessageDelegate(request),
client_id_(client_id),
request_(request),
ready_(false),
deferred_(false),
- scheduler_(scheduler) {
+ scheduler_(scheduler),
+ priority_(priority),
+ fifo_ordering_(0) {
TRACE_EVENT_ASYNC_BEGIN1("net", "URLRequest", request_,
"url", request->url().spec());
}
@@ -138,9 +146,19 @@ class ResourceScheduler::ScheduledResourceRequest
}
}
+ void set_request_priority_params(const RequestPriorityParams& priority) {
+ priority_ = priority;
+ }
+ const RequestPriorityParams& get_request_priority_params() const {
+ return priority_;
+ }
const ClientId& client_id() const { return client_id_; }
net::URLRequest* url_request() { return request_; }
const net::URLRequest* url_request() const { return request_; }
+ uint32 fifo_ordering() const { return fifo_ordering_; }
+ void set_fifo_ordering(uint32 fifo_ordering) {
+ fifo_ordering_ = fifo_ordering;
+ }
private:
// ResourceMessageDelegate interface:
@@ -163,8 +181,9 @@ class ResourceScheduler::ScheduledResourceRequest
return "ResourceScheduler";
}
- void DidChangePriority(int request_id, net::RequestPriority new_priority) {
- scheduler_->ReprioritizeRequest(this, new_priority);
+ void DidChangePriority(int request_id, net::RequestPriority new_priority,
+ int intra_priority_value) {
+ scheduler_->ReprioritizeRequest(this, new_priority, intra_priority_value);
}
ClientId client_id_;
@@ -172,10 +191,35 @@ class ResourceScheduler::ScheduledResourceRequest
bool ready_;
bool deferred_;
ResourceScheduler* scheduler_;
+ RequestPriorityParams priority_;
+ uint32 fifo_ordering_;
DISALLOW_COPY_AND_ASSIGN(ScheduledResourceRequest);
};
+bool ResourceScheduler::ScheduledResourceSorter::operator()(
+ const ScheduledResourceRequest* a,
+ const ScheduledResourceRequest* b) const {
+ // Want the set to be ordered first by decreasing priority, then by
+ // decreasing intra_priority.
+ // ie. with (priority, intra_priority)
+ // [(1, 0), (1, 0), (0, 100), (0, 0)]
+ if (a->get_request_priority_params() != b->get_request_priority_params())
+ return a->get_request_priority_params().GetSortingValue(
+ b->get_request_priority_params());
+
+ // If priority/intra_priority is the same, fall back to fifo ordering.
+ // std::multiset doesn't guarantee this until c++11.
+ return a->fifo_ordering() < b->fifo_ordering();
+}
+
+void ResourceScheduler::RequestQueue::Insert(
+ ScheduledResourceRequest* request) {
+ DCHECK(!ContainsKey(pointers_, request));
+ request->set_fifo_ordering(MakeFifoOrderingId());
+ pointers_[request] = queue_.insert(request);
+}
+
// Each client represents a tab.
struct ResourceScheduler::Client {
Client() : has_body(false), using_spdy_proxy(false) {}
@@ -202,7 +246,8 @@ scoped_ptr<ResourceThrottle> ResourceScheduler::ScheduleRequest(
DCHECK(CalledOnValidThread());
ClientId client_id = MakeClientId(child_id, route_id);
scoped_ptr<ScheduledResourceRequest> request(
- new ScheduledResourceRequest(client_id, url_request, this));
+ new ScheduledResourceRequest(client_id, url_request, this,
+ RequestPriorityParams(url_request->priority(), 0)));
ClientMap::iterator it = client_map_.find(client_id);
if (it == client_map_.end()) {
@@ -219,7 +264,7 @@ scoped_ptr<ResourceThrottle> ResourceScheduler::ScheduleRequest(
if (ShouldStartRequest(request.get(), client) == START_REQUEST) {
StartRequest(request.get(), client);
} else {
- client->pending_requests.Insert(request.get(), url_request->priority());
+ client->pending_requests.Insert(request.get());
}
return request.PassAs<ResourceThrottle>();
}
@@ -336,22 +381,33 @@ void ResourceScheduler::StartRequest(ScheduledResourceRequest* request,
}
void ResourceScheduler::ReprioritizeRequest(ScheduledResourceRequest* request,
- net::RequestPriority new_priority) {
+ net::RequestPriority new_priority,
+ int new_intra_priority_value) {
if (request->url_request()->load_flags() & net::LOAD_IGNORE_LIMITS) {
// We should not be re-prioritizing requests with the
// IGNORE_LIMITS flag.
NOTREACHED();
return;
}
- net::RequestPriority old_priority = request->url_request()->priority();
- DCHECK_NE(new_priority, old_priority);
- request->url_request()->SetPriority(new_priority);
+
+ RequestPriorityParams new_priority_params(new_priority,
+ new_intra_priority_value);
+ RequestPriorityParams old_priority_params =
+ request->get_request_priority_params();
+
+ DCHECK(old_priority_params != new_priority_params);
+
+ request->url_request()->SetPriority(new_priority_params.priority);
+ request->set_request_priority_params(new_priority_params);
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.
return;
}
+ if (old_priority_params == new_priority_params)
+ return;
+
Client *client = client_it->second;
if (!client->pending_requests.IsQueued(request)) {
DCHECK(ContainsKey(client->in_flight_requests, request));
@@ -360,10 +416,9 @@ void ResourceScheduler::ReprioritizeRequest(ScheduledResourceRequest* request,
}
client->pending_requests.Erase(request);
- client->pending_requests.Insert(request,
- request->url_request()->priority());
+ client->pending_requests.Insert(request);
- if (new_priority > old_priority) {
+ if (new_priority_params.priority > old_priority_params.priority) {
// Check if this request is now able to load at its new priority.
LoadAnyStartablePendingRequests(client);
}
@@ -378,12 +433,10 @@ void ResourceScheduler::LoadAnyStartablePendingRequests(Client* client) {
// the previous request still in the list.
// 3) We do not start the request, same as above, but StartRequest() tells
// us there's no point in checking any further requests.
-
- RequestQueue::Iterator request_iter =
+ RequestQueue::NetQueue::iterator request_iter =
client->pending_requests.GetNextHighestIterator();
-
- while (!request_iter.is_null()) {
- ScheduledResourceRequest* request = request_iter.value();
+ while (request_iter != client->pending_requests.End()) {
+ ScheduledResourceRequest* request = *request_iter;
ShouldStartReqResult query_result = ShouldStartRequest(request, client);
if (query_result == START_REQUEST) {
@@ -393,7 +446,8 @@ void ResourceScheduler::LoadAnyStartablePendingRequests(Client* client) {
// StartRequest can modify the pending list, so we (re)start evaluation
// from the currently highest priority request. Avoid copying a singular
// iterator, which would trigger undefined behavior.
- if (client->pending_requests.GetNextHighestIterator().is_null())
+ if (client->pending_requests.GetNextHighestIterator() ==
+ client->pending_requests.End())
break;
request_iter = client->pending_requests.GetNextHighestIterator();
} else if (query_result == DO_NOT_START_REQUEST_AND_KEEP_SEARCHING) {
« 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