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

Side by Side Diff: content/browser/loader/resource_scheduler.cc

Issue 1285863003: ResourceScheduler: remove dependency on ResourceRequestInfo and request_id (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@lkgr
Patch Set: Minor fixes. Created 5 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <set> 5 #include <set>
6 6
7 #include "content/browser/loader/resource_scheduler.h" 7 #include "content/browser/loader/resource_scheduler.h"
8 8
9 #include "base/metrics/field_trial.h" 9 #include "base/metrics/field_trial.h"
10 #include "base/metrics/histogram.h" 10 #include "base/metrics/histogram.h"
11 #include "base/stl_util.h" 11 #include "base/stl_util.h"
12 #include "base/strings/string_number_conversions.h" 12 #include "base/strings/string_number_conversions.h"
13 #include "base/strings/string_piece.h" 13 #include "base/strings/string_piece.h"
14 #include "base/supports_user_data.h"
14 #include "base/time/time.h" 15 #include "base/time/time.h"
15 #include "content/common/resource_messages.h" 16 #include "content/common/resource_messages.h"
16 #include "content/browser/loader/resource_message_delegate.h"
17 #include "content/public/browser/resource_controller.h" 17 #include "content/public/browser/resource_controller.h"
18 #include "content/public/browser/resource_request_info.h" 18 #include "content/public/browser/resource_request_info.h"
19 #include "content/public/browser/resource_throttle.h" 19 #include "content/public/browser/resource_throttle.h"
20 #include "ipc/ipc_message_macros.h"
21 #include "net/base/host_port_pair.h" 20 #include "net/base/host_port_pair.h"
22 #include "net/base/load_flags.h" 21 #include "net/base/load_flags.h"
23 #include "net/base/request_priority.h" 22 #include "net/base/request_priority.h"
24 #include "net/http/http_server_properties.h" 23 #include "net/http/http_server_properties.h"
25 #include "net/url_request/url_request.h" 24 #include "net/url_request/url_request.h"
26 #include "net/url_request/url_request_context.h" 25 #include "net/url_request/url_request_context.h"
27 26
28 namespace content { 27 namespace content {
29 28
30 namespace { 29 namespace {
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
103 return priority > other.priority; 102 return priority > other.priority;
104 return intra_priority > other.intra_priority; 103 return intra_priority > other.intra_priority;
105 } 104 }
106 105
107 net::RequestPriority priority; 106 net::RequestPriority priority;
108 int intra_priority; 107 int intra_priority;
109 }; 108 };
110 109
111 class ResourceScheduler::RequestQueue { 110 class ResourceScheduler::RequestQueue {
112 public: 111 public:
113 typedef std::multiset<ScheduledResourceRequest*, ScheduledResourceSorter> 112 typedef std::multiset<ScheduledResourceRequestImpl*, ScheduledResourceSorter>
114 NetQueue; 113 NetQueue;
115 114
116 RequestQueue() : fifo_ordering_ids_(0) {} 115 RequestQueue() : fifo_ordering_ids_(0) {}
117 ~RequestQueue() {} 116 ~RequestQueue() {}
118 117
119 // Adds |request| to the queue with given |priority|. 118 // Adds |request| to the queue with given |priority|.
120 void Insert(ScheduledResourceRequest* request); 119 void Insert(ScheduledResourceRequestImpl* request);
121 120
122 // Removes |request| from the queue. 121 // Removes |request| from the queue.
123 void Erase(ScheduledResourceRequest* request) { 122 void Erase(ScheduledResourceRequestImpl* request) {
124 PointerMap::iterator it = pointers_.find(request); 123 PointerMap::iterator it = pointers_.find(request);
125 DCHECK(it != pointers_.end()); 124 DCHECK(it != pointers_.end());
126 if (it == pointers_.end()) 125 if (it == pointers_.end())
127 return; 126 return;
128 queue_.erase(it->second); 127 queue_.erase(it->second);
129 pointers_.erase(it); 128 pointers_.erase(it);
130 } 129 }
131 130
132 NetQueue::iterator GetNextHighestIterator() { 131 NetQueue::iterator GetNextHighestIterator() {
133 return queue_.begin(); 132 return queue_.begin();
134 } 133 }
135 134
136 NetQueue::iterator End() { 135 NetQueue::iterator End() {
137 return queue_.end(); 136 return queue_.end();
138 } 137 }
139 138
140 // Returns true if |request| is queued. 139 // Returns true if |request| is queued.
141 bool IsQueued(ScheduledResourceRequest* request) const { 140 bool IsQueued(ScheduledResourceRequestImpl* request) const {
142 return ContainsKey(pointers_, request); 141 return ContainsKey(pointers_, request);
143 } 142 }
144 143
145 // Returns true if no requests are queued. 144 // Returns true if no requests are queued.
146 bool IsEmpty() const { return queue_.size() == 0; } 145 bool IsEmpty() const { return queue_.size() == 0; }
147 146
148 private: 147 private:
149 typedef std::map<ScheduledResourceRequest*, NetQueue::iterator> PointerMap; 148 typedef std::map<ScheduledResourceRequestImpl*, NetQueue::iterator>
149 PointerMap;
150 150
151 uint32 MakeFifoOrderingId() { 151 uint32 MakeFifoOrderingId() {
152 fifo_ordering_ids_ += 1; 152 fifo_ordering_ids_ += 1;
153 return fifo_ordering_ids_; 153 return fifo_ordering_ids_;
154 } 154 }
155 155
156 // Used to create an ordering ID for scheduled resources so that resources 156 // Used to create an ordering ID for scheduled resources so that resources
157 // with same priority/intra_priority stay in fifo order. 157 // with same priority/intra_priority stay in fifo order.
158 uint32 fifo_ordering_ids_; 158 uint32 fifo_ordering_ids_;
159 159
160 NetQueue queue_; 160 NetQueue queue_;
161 PointerMap pointers_; 161 PointerMap pointers_;
162 }; 162 };
163 163
164 // This is the handle we return to the ResourceDispatcherHostImpl so it can 164 // This is the handle we return to the ResourceDispatcherHostImpl so it can
165 // interact with the request. 165 // interact with the request.
166 class ResourceScheduler::ScheduledResourceRequest 166 class ResourceScheduler::ScheduledResourceRequestImpl
167 : public ResourceMessageDelegate, 167 : public ScheduledResourceRequest {
168 public ResourceThrottle {
169 public: 168 public:
170 ScheduledResourceRequest(const ClientId& client_id, 169 ScheduledResourceRequestImpl(const ClientId& client_id,
171 net::URLRequest* request, 170 net::URLRequest* request,
172 ResourceScheduler* scheduler, 171 ResourceScheduler* scheduler,
173 const RequestPriorityParams& priority) 172 const RequestPriorityParams& priority,
174 : ResourceMessageDelegate(request), 173 bool is_async)
175 client_id_(client_id), 174 : client_id_(client_id),
176 client_state_on_creation_(scheduler->GetClientState(client_id_)), 175 client_state_on_creation_(scheduler->GetClientState(client_id_)),
177 request_(request), 176 request_(request),
178 ready_(false), 177 ready_(false),
179 deferred_(false), 178 deferred_(false),
179 is_async_(is_async),
180 classification_(NORMAL_REQUEST), 180 classification_(NORMAL_REQUEST),
181 scheduler_(scheduler), 181 scheduler_(scheduler),
182 priority_(priority), 182 priority_(priority),
183 fifo_ordering_(0) { 183 fifo_ordering_(0) {
184 request_->SetUserData(kUserDataKey, new UnownedPointer(this));
184 } 185 }
185 186
186 ~ScheduledResourceRequest() override { scheduler_->RemoveRequest(this); } 187 ~ScheduledResourceRequestImpl() override {
188 request_->RemoveUserData(kUserDataKey);
189 scheduler_->RemoveRequest(this);
190 }
191
192 void ChangePriority(net::RequestPriority new_priority,
193 int intra_priority_value) override {
194 scheduler_->ReprioritizeRequest(this, new_priority, intra_priority_value);
195 }
196
197 static ScheduledResourceRequest* ForRequest(net::URLRequest* request) {
198 return static_cast<UnownedPointer*>(request->GetUserData(kUserDataKey))
199 ->pointer;
200 }
187 201
188 void Start() { 202 void Start() {
189 ready_ = true; 203 ready_ = true;
190 if (!request_->status().is_success()) 204 if (!request_->status().is_success())
191 return; 205 return;
192 base::TimeTicks time = base::TimeTicks::Now(); 206 base::TimeTicks time = base::TimeTicks::Now();
193 ClientState current_state = scheduler_->GetClientState(client_id_); 207 ClientState current_state = scheduler_->GetClientState(client_id_);
194 // Note: the client state isn't perfectly accurate since it won't capture 208 // Note: the client state isn't perfectly accurate since it won't capture
195 // tabs which have switched between active and background multiple times. 209 // tabs which have switched between active and background multiple times.
196 // Ex: A tab with the following transitions Active -> Background -> Active 210 // Ex: A tab with the following transitions Active -> Background -> Active
(...skipping 22 matching lines...) Expand all
219 233
220 void set_request_priority_params(const RequestPriorityParams& priority) { 234 void set_request_priority_params(const RequestPriorityParams& priority) {
221 priority_ = priority; 235 priority_ = priority;
222 } 236 }
223 const RequestPriorityParams& get_request_priority_params() const { 237 const RequestPriorityParams& get_request_priority_params() const {
224 return priority_; 238 return priority_;
225 } 239 }
226 const ClientId& client_id() const { return client_id_; } 240 const ClientId& client_id() const { return client_id_; }
227 net::URLRequest* url_request() { return request_; } 241 net::URLRequest* url_request() { return request_; }
228 const net::URLRequest* url_request() const { return request_; } 242 const net::URLRequest* url_request() const { return request_; }
243 bool is_async() const { return is_async_; }
229 uint32 fifo_ordering() const { return fifo_ordering_; } 244 uint32 fifo_ordering() const { return fifo_ordering_; }
230 void set_fifo_ordering(uint32 fifo_ordering) { 245 void set_fifo_ordering(uint32 fifo_ordering) {
231 fifo_ordering_ = fifo_ordering; 246 fifo_ordering_ = fifo_ordering;
232 } 247 }
233 RequestClassification classification() const { 248 RequestClassification classification() const {
234 return classification_; 249 return classification_;
235 } 250 }
236 void set_classification(RequestClassification classification) { 251 void set_classification(RequestClassification classification) {
237 classification_ = classification; 252 classification_ = classification;
238 } 253 }
239 254
240 private: 255 private:
241 // ResourceMessageDelegate interface: 256 class UnownedPointer : public base::SupportsUserData::Data {
242 bool OnMessageReceived(const IPC::Message& message) override { 257 public:
243 bool handled = true; 258 UnownedPointer(ScheduledResourceRequestImpl* pointer) : pointer(pointer) {}
davidben 2015/08/13 23:08:52 Nit: Maybe a newline here? Not sure. Was a bit har
Adam Rice 2015/08/13 23:42:28 Done.
244 IPC_BEGIN_MESSAGE_MAP(ScheduledResourceRequest, message) 259 ScheduledResourceRequestImpl* const pointer;
245 IPC_MESSAGE_HANDLER(ResourceHostMsg_DidChangePriority, DidChangePriority) 260
246 IPC_MESSAGE_UNHANDLED(handled = false) 261 private:
247 IPC_END_MESSAGE_MAP() 262 DISALLOW_COPY_AND_ASSIGN(UnownedPointer);
248 return handled; 263 };
249 } 264
265 static const void* const kUserDataKey;
250 266
251 // ResourceThrottle interface: 267 // ResourceThrottle interface:
252 void WillStartRequest(bool* defer) override { 268 void WillStartRequest(bool* defer) override {
253 deferred_ = *defer = !ready_; 269 deferred_ = *defer = !ready_;
254 time_deferred_ = base::TimeTicks::Now(); 270 time_deferred_ = base::TimeTicks::Now();
255 } 271 }
256 272
257 const char* GetNameForLogging() const override { return "ResourceScheduler"; } 273 const char* GetNameForLogging() const override { return "ResourceScheduler"; }
258 274
259 void DidChangePriority(int request_id, net::RequestPriority new_priority,
260 int intra_priority_value) {
261 scheduler_->ReprioritizeRequest(this, new_priority, intra_priority_value);
262 }
263
264 const ClientId client_id_; 275 const ClientId client_id_;
265 const ResourceScheduler::ClientState client_state_on_creation_; 276 const ResourceScheduler::ClientState client_state_on_creation_;
266 net::URLRequest* request_; 277 net::URLRequest* request_;
267 bool ready_; 278 bool ready_;
268 bool deferred_; 279 bool deferred_;
280 bool is_async_;
269 RequestClassification classification_; 281 RequestClassification classification_;
270 ResourceScheduler* scheduler_; 282 ResourceScheduler* scheduler_;
271 RequestPriorityParams priority_; 283 RequestPriorityParams priority_;
272 uint32 fifo_ordering_; 284 uint32 fifo_ordering_;
273 base::TimeTicks time_deferred_; 285 base::TimeTicks time_deferred_;
274 286
275 DISALLOW_COPY_AND_ASSIGN(ScheduledResourceRequest); 287 DISALLOW_COPY_AND_ASSIGN(ScheduledResourceRequestImpl);
276 }; 288 };
277 289
290 const void* const
291 ResourceScheduler::ScheduledResourceRequestImpl::kUserDataKey =
292 &ResourceScheduler::ScheduledResourceRequestImpl::kUserDataKey;
davidben 2015/08/13 23:08:53 [Ah the sweet music of C++. You can tell it's musi
Adam Rice 2015/08/13 23:42:28 I have to admit I borrowed this trick from someone
293
294 ResourceScheduler::ScheduledResourceRequest::ScheduledResourceRequest() {}
295 ResourceScheduler::ScheduledResourceRequest::~ScheduledResourceRequest() {}
296 ResourceScheduler::ScheduledResourceRequest*
297 ResourceScheduler::ScheduledResourceRequest::ForRequest(
298 net::URLRequest* request) {
299 return ResourceScheduler::ScheduledResourceRequestImpl::ForRequest(request);
300 }
301
278 bool ResourceScheduler::ScheduledResourceSorter::operator()( 302 bool ResourceScheduler::ScheduledResourceSorter::operator()(
279 const ScheduledResourceRequest* a, 303 const ScheduledResourceRequestImpl* a,
280 const ScheduledResourceRequest* b) const { 304 const ScheduledResourceRequestImpl* b) const {
281 // Want the set to be ordered first by decreasing priority, then by 305 // Want the set to be ordered first by decreasing priority, then by
282 // decreasing intra_priority. 306 // decreasing intra_priority.
283 // ie. with (priority, intra_priority) 307 // ie. with (priority, intra_priority)
284 // [(1, 0), (1, 0), (0, 100), (0, 0)] 308 // [(1, 0), (1, 0), (0, 100), (0, 0)]
285 if (a->get_request_priority_params() != b->get_request_priority_params()) 309 if (a->get_request_priority_params() != b->get_request_priority_params())
286 return a->get_request_priority_params().GreaterThan( 310 return a->get_request_priority_params().GreaterThan(
287 b->get_request_priority_params()); 311 b->get_request_priority_params());
288 312
289 // If priority/intra_priority is the same, fall back to fifo ordering. 313 // If priority/intra_priority is the same, fall back to fifo ordering.
290 // std::multiset doesn't guarantee this until c++11. 314 // std::multiset doesn't guarantee this until c++11.
291 return a->fifo_ordering() < b->fifo_ordering(); 315 return a->fifo_ordering() < b->fifo_ordering();
292 } 316 }
293 317
294 void ResourceScheduler::RequestQueue::Insert( 318 void ResourceScheduler::RequestQueue::Insert(
295 ScheduledResourceRequest* request) { 319 ScheduledResourceRequestImpl* request) {
296 DCHECK(!ContainsKey(pointers_, request)); 320 DCHECK(!ContainsKey(pointers_, request));
297 request->set_fifo_ordering(MakeFifoOrderingId()); 321 request->set_fifo_ordering(MakeFifoOrderingId());
298 pointers_[request] = queue_.insert(request); 322 pointers_[request] = queue_.insert(request);
299 } 323 }
300 324
301 // Each client represents a tab. 325 // Each client represents a tab.
302 class ResourceScheduler::Client { 326 class ResourceScheduler::Client {
303 public: 327 public:
304 explicit Client(ResourceScheduler* scheduler, 328 explicit Client(ResourceScheduler* scheduler,
305 bool is_visible, 329 bool is_visible,
(...skipping 12 matching lines...) Expand all
318 342
319 ~Client() { 343 ~Client() {
320 // Update to default state and pause to ensure the scheduler has a 344 // Update to default state and pause to ensure the scheduler has a
321 // correct count of relevant types of clients. 345 // correct count of relevant types of clients.
322 is_visible_ = false; 346 is_visible_ = false;
323 is_audible_ = false; 347 is_audible_ = false;
324 is_paused_ = true; 348 is_paused_ = true;
325 UpdateThrottleState(); 349 UpdateThrottleState();
326 } 350 }
327 351
328 void ScheduleRequest( 352 void ScheduleRequest(net::URLRequest* url_request,
329 net::URLRequest* url_request, 353 ScheduledResourceRequestImpl* request) {
330 ScheduledResourceRequest* request) {
331 if (ShouldStartRequest(request) == START_REQUEST) 354 if (ShouldStartRequest(request) == START_REQUEST)
332 StartRequest(request); 355 StartRequest(request);
333 else 356 else
334 pending_requests_.Insert(request); 357 pending_requests_.Insert(request);
335 SetRequestClassification(request, ClassifyRequest(request)); 358 SetRequestClassification(request, ClassifyRequest(request));
336 } 359 }
337 360
338 void RemoveRequest(ScheduledResourceRequest* request) { 361 void RemoveRequest(ScheduledResourceRequestImpl* request) {
339 if (pending_requests_.IsQueued(request)) { 362 if (pending_requests_.IsQueued(request)) {
340 pending_requests_.Erase(request); 363 pending_requests_.Erase(request);
341 DCHECK(!ContainsKey(in_flight_requests_, request)); 364 DCHECK(!ContainsKey(in_flight_requests_, request));
342 } else { 365 } else {
343 EraseInFlightRequest(request); 366 EraseInFlightRequest(request);
344 367
345 // Removing this request may have freed up another to load. 368 // Removing this request may have freed up another to load.
346 LoadAnyStartablePendingRequests(); 369 LoadAnyStartablePendingRequests();
347 } 370 }
348 } 371 }
349 372
350 RequestSet StartAndRemoveAllRequests() { 373 RequestSet StartAndRemoveAllRequests() {
351 // First start any pending requests so that they will be moved into 374 // First start any pending requests so that they will be moved into
352 // in_flight_requests_. This may exceed the limits 375 // in_flight_requests_. This may exceed the limits
353 // kMaxNumDelayableRequestsPerClient, kMaxNumDelayableRequestsPerHost and 376 // kMaxNumDelayableRequestsPerClient, kMaxNumDelayableRequestsPerHost and
354 // kMaxNumThrottledRequestsPerClient, so this method must not do anything 377 // kMaxNumThrottledRequestsPerClient, so this method must not do anything
355 // that depends on those limits before calling ClearInFlightRequests() 378 // that depends on those limits before calling ClearInFlightRequests()
356 // below. 379 // below.
357 while (!pending_requests_.IsEmpty()) { 380 while (!pending_requests_.IsEmpty()) {
358 ScheduledResourceRequest* request = 381 ScheduledResourceRequestImpl* request =
359 *pending_requests_.GetNextHighestIterator(); 382 *pending_requests_.GetNextHighestIterator();
360 pending_requests_.Erase(request); 383 pending_requests_.Erase(request);
361 // StartRequest() may modify pending_requests_. TODO(ricea): Does it? 384 // StartRequest() may modify pending_requests_. TODO(ricea): Does it?
362 StartRequest(request); 385 StartRequest(request);
363 } 386 }
364 RequestSet unowned_requests; 387 RequestSet unowned_requests;
365 for (RequestSet::iterator it = in_flight_requests_.begin(); 388 for (RequestSet::iterator it = in_flight_requests_.begin();
366 it != in_flight_requests_.end(); ++it) { 389 it != in_flight_requests_.end(); ++it) {
367 unowned_requests.insert(*it); 390 unowned_requests.insert(*it);
368 (*it)->set_classification(NORMAL_REQUEST); 391 (*it)->set_classification(NORMAL_REQUEST);
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
479 LoadAnyStartablePendingRequests(); 502 LoadAnyStartablePendingRequests();
480 } 503 }
481 504
482 void OnReceivedSpdyProxiedHttpResponse() { 505 void OnReceivedSpdyProxiedHttpResponse() {
483 if (!using_spdy_proxy_) { 506 if (!using_spdy_proxy_) {
484 using_spdy_proxy_ = true; 507 using_spdy_proxy_ = true;
485 LoadAnyStartablePendingRequests(); 508 LoadAnyStartablePendingRequests();
486 } 509 }
487 } 510 }
488 511
489 void ReprioritizeRequest(ScheduledResourceRequest* request, 512 void ReprioritizeRequest(ScheduledResourceRequestImpl* request,
490 RequestPriorityParams old_priority_params, 513 RequestPriorityParams old_priority_params,
491 RequestPriorityParams new_priority_params) { 514 RequestPriorityParams new_priority_params) {
492 request->url_request()->SetPriority(new_priority_params.priority); 515 request->url_request()->SetPriority(new_priority_params.priority);
493 request->set_request_priority_params(new_priority_params); 516 request->set_request_priority_params(new_priority_params);
494 if (!pending_requests_.IsQueued(request)) { 517 if (!pending_requests_.IsQueued(request)) {
495 DCHECK(ContainsKey(in_flight_requests_, request)); 518 DCHECK(ContainsKey(in_flight_requests_, request));
496 // The priority of the request and priority support of the server may 519 // The priority of the request and priority support of the server may
497 // have changed, so update the delayable count. 520 // have changed, so update the delayable count.
498 SetRequestClassification(request, ClassifyRequest(request)); 521 SetRequestClassification(request, ClassifyRequest(request));
499 // Request has already started. 522 // Request has already started.
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
553 SetThrottleState(COALESCED); 576 SetThrottleState(COALESCED);
554 } 577 }
555 578
556 private: 579 private:
557 enum ShouldStartReqResult { 580 enum ShouldStartReqResult {
558 DO_NOT_START_REQUEST_AND_STOP_SEARCHING, 581 DO_NOT_START_REQUEST_AND_STOP_SEARCHING,
559 DO_NOT_START_REQUEST_AND_KEEP_SEARCHING, 582 DO_NOT_START_REQUEST_AND_KEEP_SEARCHING,
560 START_REQUEST, 583 START_REQUEST,
561 }; 584 };
562 585
563 void InsertInFlightRequest(ScheduledResourceRequest* request) { 586 void InsertInFlightRequest(ScheduledResourceRequestImpl* request) {
564 in_flight_requests_.insert(request); 587 in_flight_requests_.insert(request);
565 SetRequestClassification(request, ClassifyRequest(request)); 588 SetRequestClassification(request, ClassifyRequest(request));
566 } 589 }
567 590
568 void EraseInFlightRequest(ScheduledResourceRequest* request) { 591 void EraseInFlightRequest(ScheduledResourceRequestImpl* request) {
569 size_t erased = in_flight_requests_.erase(request); 592 size_t erased = in_flight_requests_.erase(request);
570 DCHECK_EQ(1u, erased); 593 DCHECK_EQ(1u, erased);
571 // Clear any special state that we were tracking for this request. 594 // Clear any special state that we were tracking for this request.
572 SetRequestClassification(request, NORMAL_REQUEST); 595 SetRequestClassification(request, NORMAL_REQUEST);
573 } 596 }
574 597
575 void ClearInFlightRequests() { 598 void ClearInFlightRequests() {
576 in_flight_requests_.clear(); 599 in_flight_requests_.clear();
577 in_flight_delayable_count_ = 0; 600 in_flight_delayable_count_ = 0;
578 total_layout_blocking_count_ = 0; 601 total_layout_blocking_count_ = 0;
(...skipping 11 matching lines...) Expand all
590 for (RequestQueue::NetQueue::const_iterator 613 for (RequestQueue::NetQueue::const_iterator
591 it = pending_requests_.GetNextHighestIterator(); 614 it = pending_requests_.GetNextHighestIterator();
592 it != pending_requests_.End(); ++it) { 615 it != pending_requests_.End(); ++it) {
593 if ((*it)->classification() == classification) 616 if ((*it)->classification() == classification)
594 classification_request_count++; 617 classification_request_count++;
595 } 618 }
596 } 619 }
597 return classification_request_count; 620 return classification_request_count;
598 } 621 }
599 622
600 void SetRequestClassification(ScheduledResourceRequest* request, 623 void SetRequestClassification(ScheduledResourceRequestImpl* request,
601 RequestClassification classification) { 624 RequestClassification classification) {
602 RequestClassification old_classification = request->classification(); 625 RequestClassification old_classification = request->classification();
603 if (old_classification == classification) 626 if (old_classification == classification)
604 return; 627 return;
605 628
606 if (old_classification == IN_FLIGHT_DELAYABLE_REQUEST) 629 if (old_classification == IN_FLIGHT_DELAYABLE_REQUEST)
607 in_flight_delayable_count_--; 630 in_flight_delayable_count_--;
608 if (old_classification == LAYOUT_BLOCKING_REQUEST) 631 if (old_classification == LAYOUT_BLOCKING_REQUEST)
609 total_layout_blocking_count_--; 632 total_layout_blocking_count_--;
610 633
611 if (classification == IN_FLIGHT_DELAYABLE_REQUEST) 634 if (classification == IN_FLIGHT_DELAYABLE_REQUEST)
612 in_flight_delayable_count_++; 635 in_flight_delayable_count_++;
613 if (classification == LAYOUT_BLOCKING_REQUEST) 636 if (classification == LAYOUT_BLOCKING_REQUEST)
614 total_layout_blocking_count_++; 637 total_layout_blocking_count_++;
615 638
616 request->set_classification(classification); 639 request->set_classification(classification);
617 DCHECK_EQ( 640 DCHECK_EQ(
618 CountRequestsWithClassification(IN_FLIGHT_DELAYABLE_REQUEST, false), 641 CountRequestsWithClassification(IN_FLIGHT_DELAYABLE_REQUEST, false),
619 in_flight_delayable_count_); 642 in_flight_delayable_count_);
620 DCHECK_EQ(CountRequestsWithClassification(LAYOUT_BLOCKING_REQUEST, true), 643 DCHECK_EQ(CountRequestsWithClassification(LAYOUT_BLOCKING_REQUEST, true),
621 total_layout_blocking_count_); 644 total_layout_blocking_count_);
622 } 645 }
623 646
624 RequestClassification ClassifyRequest(ScheduledResourceRequest* request) { 647 RequestClassification ClassifyRequest(ScheduledResourceRequestImpl* request) {
625 // If a request is already marked as layout-blocking make sure to keep the 648 // If a request is already marked as layout-blocking make sure to keep the
626 // classification across redirects unless the priority was lowered. 649 // classification across redirects unless the priority was lowered.
627 if (request->classification() == LAYOUT_BLOCKING_REQUEST && 650 if (request->classification() == LAYOUT_BLOCKING_REQUEST &&
628 request->url_request()->priority() > net::LOW) { 651 request->url_request()->priority() > net::LOW) {
629 return LAYOUT_BLOCKING_REQUEST; 652 return LAYOUT_BLOCKING_REQUEST;
630 } 653 }
631 654
632 if (!has_body_ && request->url_request()->priority() > net::LOW) 655 if (!has_body_ && request->url_request()->priority() > net::LOW)
633 return LAYOUT_BLOCKING_REQUEST; 656 return LAYOUT_BLOCKING_REQUEST;
634 657
(...skipping 19 matching lines...) Expand all
654 net::HostPortPair::FromURL((*it)->url_request()->url()); 677 net::HostPortPair::FromURL((*it)->url_request()->url());
655 if (active_request_host.Equals(host_port_pair)) { 678 if (active_request_host.Equals(host_port_pair)) {
656 same_host_count++; 679 same_host_count++;
657 if (same_host_count >= kMaxNumDelayableRequestsPerHost) 680 if (same_host_count >= kMaxNumDelayableRequestsPerHost)
658 return true; 681 return true;
659 } 682 }
660 } 683 }
661 return false; 684 return false;
662 } 685 }
663 686
664 void StartRequest(ScheduledResourceRequest* request) { 687 void StartRequest(ScheduledResourceRequestImpl* request) {
665 InsertInFlightRequest(request); 688 InsertInFlightRequest(request);
666 request->Start(); 689 request->Start();
667 } 690 }
668 691
669 // ShouldStartRequest is the main scheduling algorithm. 692 // ShouldStartRequest is the main scheduling algorithm.
670 // 693 //
671 // Requests are evaluated on five attributes: 694 // Requests are evaluated on five attributes:
672 // 695 //
673 // 1. Non-delayable requests: 696 // 1. Non-delayable requests:
674 // * Synchronous requests. 697 // * Synchronous requests.
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
712 // * If no high priority requests are in flight, start loading low priority 735 // * If no high priority requests are in flight, start loading low priority
713 // requests. 736 // requests.
714 // 737 //
715 // COALESCED Clients never load requests, with the following exceptions: 738 // COALESCED Clients never load requests, with the following exceptions:
716 // * Non-delayable requests are issued imediately. 739 // * Non-delayable requests are issued imediately.
717 // * On a (currently 5 second) heart beat, they load all requests as an 740 // * On a (currently 5 second) heart beat, they load all requests as an
718 // UNTHROTTLED Client, and then return to the COALESCED state. 741 // UNTHROTTLED Client, and then return to the COALESCED state.
719 // * When an active Client makes a request, they are THROTTLED until the 742 // * When an active Client makes a request, they are THROTTLED until the
720 // active Client finishes loading. 743 // active Client finishes loading.
721 ShouldStartReqResult ShouldStartRequest( 744 ShouldStartReqResult ShouldStartRequest(
722 ScheduledResourceRequest* request) const { 745 ScheduledResourceRequestImpl* request) const {
723 const net::URLRequest& url_request = *request->url_request(); 746 const net::URLRequest& url_request = *request->url_request();
724 // Syncronous requests could block the entire render, which could impact 747 // Syncronous requests could block the entire render, which could impact
725 // user-observable Clients. 748 // user-observable Clients.
726 if (!ResourceRequestInfo::ForRequest(&url_request)->IsAsync()) { 749 if (!request->is_async()) {
727 return START_REQUEST; 750 return START_REQUEST;
728 } 751 }
729 752
730 // TODO(simonjam): This may end up causing disk contention. We should 753 // TODO(simonjam): This may end up causing disk contention. We should
731 // experiment with throttling if that happens. 754 // experiment with throttling if that happens.
732 // TODO(aiolos): We probably want to Coalesce these as well to avoid 755 // TODO(aiolos): We probably want to Coalesce these as well to avoid
733 // waking the disk. 756 // waking the disk.
734 if (!url_request.url().SchemeIsHTTPOrHTTPS()) { 757 if (!url_request.url().SchemeIsHTTPOrHTTPS()) {
735 return START_REQUEST; 758 return START_REQUEST;
736 } 759 }
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
803 // 1) We start the request, remove it from the list, and keep checking. 826 // 1) We start the request, remove it from the list, and keep checking.
804 // 2) We do NOT start the request, but ShouldStartRequest() signals us that 827 // 2) We do NOT start the request, but ShouldStartRequest() signals us that
805 // there may be room for other requests, so we keep checking and leave 828 // there may be room for other requests, so we keep checking and leave
806 // the previous request still in the list. 829 // the previous request still in the list.
807 // 3) We do not start the request, same as above, but StartRequest() tells 830 // 3) We do not start the request, same as above, but StartRequest() tells
808 // us there's no point in checking any further requests. 831 // us there's no point in checking any further requests.
809 RequestQueue::NetQueue::iterator request_iter = 832 RequestQueue::NetQueue::iterator request_iter =
810 pending_requests_.GetNextHighestIterator(); 833 pending_requests_.GetNextHighestIterator();
811 834
812 while (request_iter != pending_requests_.End()) { 835 while (request_iter != pending_requests_.End()) {
813 ScheduledResourceRequest* request = *request_iter; 836 ScheduledResourceRequestImpl* request = *request_iter;
814 ShouldStartReqResult query_result = ShouldStartRequest(request); 837 ShouldStartReqResult query_result = ShouldStartRequest(request);
815 838
816 if (query_result == START_REQUEST) { 839 if (query_result == START_REQUEST) {
817 pending_requests_.Erase(request); 840 pending_requests_.Erase(request);
818 StartRequest(request); 841 StartRequest(request);
819 842
820 // StartRequest can modify the pending list, so we (re)start evaluation 843 // StartRequest can modify the pending list, so we (re)start evaluation
821 // from the currently highest priority request. Avoid copying a singular 844 // from the currently highest priority request. Avoid copying a singular
822 // iterator, which would trigger undefined behavior. 845 // iterator, which would trigger undefined behavior.
823 if (pending_requests_.GetNextHighestIterator() == 846 if (pending_requests_.GetNextHighestIterator() ==
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
898 OnLoadingActiveClientsStateChangedForAllClients(); 921 OnLoadingActiveClientsStateChangedForAllClients();
899 } 922 }
900 923
901 ResourceScheduler::ClientThrottleState 924 ResourceScheduler::ClientThrottleState
902 ResourceScheduler::GetClientStateForTesting(int child_id, int route_id) { 925 ResourceScheduler::GetClientStateForTesting(int child_id, int route_id) {
903 Client* client = GetClient(child_id, route_id); 926 Client* client = GetClient(child_id, route_id);
904 DCHECK(client); 927 DCHECK(client);
905 return client->throttle_state(); 928 return client->throttle_state();
906 } 929 }
907 930
908 scoped_ptr<ResourceThrottle> ResourceScheduler::ScheduleRequest( 931 scoped_ptr<ResourceScheduler::ScheduledResourceRequest>
909 int child_id, 932 ResourceScheduler::ScheduleRequest(int child_id,
910 int route_id, 933 int route_id,
911 net::URLRequest* url_request) { 934 bool is_async,
935 net::URLRequest* url_request) {
912 DCHECK(CalledOnValidThread()); 936 DCHECK(CalledOnValidThread());
913 ClientId client_id = MakeClientId(child_id, route_id); 937 ClientId client_id = MakeClientId(child_id, route_id);
914 scoped_ptr<ScheduledResourceRequest> request(new ScheduledResourceRequest( 938 scoped_ptr<ScheduledResourceRequestImpl> request(
915 client_id, 939 new ScheduledResourceRequestImpl(
916 url_request, 940 client_id, url_request, this,
917 this, 941 RequestPriorityParams(url_request->priority(), 0), is_async));
918 RequestPriorityParams(url_request->priority(), 0)));
919 942
920 ClientMap::iterator it = client_map_.find(client_id); 943 ClientMap::iterator it = client_map_.find(client_id);
921 if (it == client_map_.end()) { 944 if (it == client_map_.end()) {
922 // There are several ways this could happen: 945 // There are several ways this could happen:
923 // 1. <a ping> requests don't have a route_id. 946 // 1. <a ping> requests don't have a route_id.
924 // 2. Most unittests don't send the IPCs needed to register Clients. 947 // 2. Most unittests don't send the IPCs needed to register Clients.
925 // 3. The tab is closed while a RequestResource IPC is in flight. 948 // 3. The tab is closed while a RequestResource IPC is in flight.
926 unowned_requests_.insert(request.get()); 949 unowned_requests_.insert(request.get());
927 request->Start(); 950 request->Start();
928 return request.Pass(); 951 return request.Pass();
929 } 952 }
930 953
931 Client* client = it->second; 954 Client* client = it->second;
932 client->ScheduleRequest(url_request, request.get()); 955 client->ScheduleRequest(url_request, request.get());
933 return request.Pass(); 956 return request.Pass();
934 } 957 }
935 958
936 void ResourceScheduler::RemoveRequest(ScheduledResourceRequest* request) { 959 void ResourceScheduler::RemoveRequest(ScheduledResourceRequestImpl* request) {
937 DCHECK(CalledOnValidThread()); 960 DCHECK(CalledOnValidThread());
938 if (ContainsKey(unowned_requests_, request)) { 961 if (ContainsKey(unowned_requests_, request)) {
939 unowned_requests_.erase(request); 962 unowned_requests_.erase(request);
940 return; 963 return;
941 } 964 }
942 965
943 ClientMap::iterator client_it = client_map_.find(request->client_id()); 966 ClientMap::iterator client_it = client_map_.find(request->client_id());
944 if (client_it == client_map_.end()) { 967 if (client_it == client_map_.end()) {
945 return; 968 return;
946 } 969 }
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after
1164 } 1187 }
1165 1188
1166 ResourceScheduler::ClientState ResourceScheduler::GetClientState( 1189 ResourceScheduler::ClientState ResourceScheduler::GetClientState(
1167 ClientId client_id) const { 1190 ClientId client_id) const {
1168 ClientMap::const_iterator client_it = client_map_.find(client_id); 1191 ClientMap::const_iterator client_it = client_map_.find(client_id);
1169 if (client_it == client_map_.end()) 1192 if (client_it == client_map_.end())
1170 return UNKNOWN; 1193 return UNKNOWN;
1171 return client_it->second->is_active() ? ACTIVE : BACKGROUND; 1194 return client_it->second->is_active() ? ACTIVE : BACKGROUND;
1172 } 1195 }
1173 1196
1174 void ResourceScheduler::ReprioritizeRequest(ScheduledResourceRequest* request, 1197 void ResourceScheduler::ReprioritizeRequest(
1175 net::RequestPriority new_priority, 1198 ScheduledResourceRequestImpl* request,
1176 int new_intra_priority_value) { 1199 net::RequestPriority new_priority,
1200 int new_intra_priority_value) {
1177 if (request->url_request()->load_flags() & net::LOAD_IGNORE_LIMITS) { 1201 if (request->url_request()->load_flags() & net::LOAD_IGNORE_LIMITS) {
1178 // We should not be re-prioritizing requests with the 1202 // We should not be re-prioritizing requests with the
1179 // IGNORE_LIMITS flag. 1203 // IGNORE_LIMITS flag.
1180 NOTREACHED(); 1204 NOTREACHED();
1181 return; 1205 return;
1182 } 1206 }
1183 RequestPriorityParams new_priority_params(new_priority, 1207 RequestPriorityParams new_priority_params(new_priority,
1184 new_intra_priority_value); 1208 new_intra_priority_value);
1185 RequestPriorityParams old_priority_params = 1209 RequestPriorityParams old_priority_params =
1186 request->get_request_priority_params(); 1210 request->get_request_priority_params();
(...skipping 15 matching lines...) Expand all
1202 client->ReprioritizeRequest( 1226 client->ReprioritizeRequest(
1203 request, old_priority_params, new_priority_params); 1227 request, old_priority_params, new_priority_params);
1204 } 1228 }
1205 1229
1206 ResourceScheduler::ClientId ResourceScheduler::MakeClientId( 1230 ResourceScheduler::ClientId ResourceScheduler::MakeClientId(
1207 int child_id, int route_id) { 1231 int child_id, int route_id) {
1208 return (static_cast<ResourceScheduler::ClientId>(child_id) << 32) | route_id; 1232 return (static_cast<ResourceScheduler::ClientId>(child_id) << 32) | route_id;
1209 } 1233 }
1210 1234
1211 } // namespace content 1235 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698