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

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: Fix tests. 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/time/time.h" 14 #include "base/time/time.h"
15 #include "content/common/resource_messages.h" 15 #include "content/common/resource_messages.h"
16 #include "content/browser/loader/resource_message_delegate.h"
17 #include "content/public/browser/resource_controller.h" 16 #include "content/public/browser/resource_controller.h"
18 #include "content/public/browser/resource_request_info.h" 17 #include "content/public/browser/resource_request_info.h"
19 #include "content/public/browser/resource_throttle.h" 18 #include "content/public/browser/resource_throttle.h"
20 #include "ipc/ipc_message_macros.h"
21 #include "net/base/host_port_pair.h" 19 #include "net/base/host_port_pair.h"
22 #include "net/base/load_flags.h" 20 #include "net/base/load_flags.h"
23 #include "net/base/request_priority.h" 21 #include "net/base/request_priority.h"
24 #include "net/http/http_server_properties.h" 22 #include "net/http/http_server_properties.h"
25 #include "net/url_request/url_request.h" 23 #include "net/url_request/url_request.h"
26 #include "net/url_request/url_request_context.h" 24 #include "net/url_request/url_request_context.h"
27 25
28 namespace content { 26 namespace content {
29 27
30 namespace { 28 namespace {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
71 return "Over30Clients"; 69 return "Over30Clients";
72 } 70 }
73 71
74 } // namespace 72 } // namespace
75 73
76 static const size_t kCoalescedTimerPeriod = 5000; 74 static const size_t kCoalescedTimerPeriod = 5000;
77 static const size_t kMaxNumDelayableRequestsPerClient = 10; 75 static const size_t kMaxNumDelayableRequestsPerClient = 10;
78 static const size_t kMaxNumDelayableRequestsPerHost = 6; 76 static const size_t kMaxNumDelayableRequestsPerHost = 6;
79 static const size_t kMaxNumThrottledRequestsPerClient = 1; 77 static const size_t kMaxNumThrottledRequestsPerClient = 1;
80 78
79 ScheduledResourceRequest::ScheduledResourceRequest() {}
80 ScheduledResourceRequest::~ScheduledResourceRequest() {}
81
81 struct ResourceScheduler::RequestPriorityParams { 82 struct ResourceScheduler::RequestPriorityParams {
82 RequestPriorityParams() 83 RequestPriorityParams()
83 : priority(net::DEFAULT_PRIORITY), 84 : priority(net::DEFAULT_PRIORITY),
84 intra_priority(0) { 85 intra_priority(0) {
85 } 86 }
86 87
87 RequestPriorityParams(net::RequestPriority priority, int intra_priority) 88 RequestPriorityParams(net::RequestPriority priority, int intra_priority)
88 : priority(priority), 89 : priority(priority),
89 intra_priority(intra_priority) { 90 intra_priority(intra_priority) {
90 } 91 }
(...skipping 12 matching lines...) Expand all
103 return priority > other.priority; 104 return priority > other.priority;
104 return intra_priority > other.intra_priority; 105 return intra_priority > other.intra_priority;
105 } 106 }
106 107
107 net::RequestPriority priority; 108 net::RequestPriority priority;
108 int intra_priority; 109 int intra_priority;
109 }; 110 };
110 111
111 class ResourceScheduler::RequestQueue { 112 class ResourceScheduler::RequestQueue {
112 public: 113 public:
113 typedef std::multiset<ScheduledResourceRequest*, ScheduledResourceSorter> 114 typedef std::multiset<ScheduledResourceRequestImpl*, ScheduledResourceSorter>
114 NetQueue; 115 NetQueue;
115 116
116 RequestQueue() : fifo_ordering_ids_(0) {} 117 RequestQueue() : fifo_ordering_ids_(0) {}
117 ~RequestQueue() {} 118 ~RequestQueue() {}
118 119
119 // Adds |request| to the queue with given |priority|. 120 // Adds |request| to the queue with given |priority|.
120 void Insert(ScheduledResourceRequest* request); 121 void Insert(ScheduledResourceRequestImpl* request);
121 122
122 // Removes |request| from the queue. 123 // Removes |request| from the queue.
123 void Erase(ScheduledResourceRequest* request) { 124 void Erase(ScheduledResourceRequestImpl* request) {
124 PointerMap::iterator it = pointers_.find(request); 125 PointerMap::iterator it = pointers_.find(request);
125 DCHECK(it != pointers_.end()); 126 DCHECK(it != pointers_.end());
126 if (it == pointers_.end()) 127 if (it == pointers_.end())
127 return; 128 return;
128 queue_.erase(it->second); 129 queue_.erase(it->second);
129 pointers_.erase(it); 130 pointers_.erase(it);
130 } 131 }
131 132
132 NetQueue::iterator GetNextHighestIterator() { 133 NetQueue::iterator GetNextHighestIterator() {
133 return queue_.begin(); 134 return queue_.begin();
134 } 135 }
135 136
136 NetQueue::iterator End() { 137 NetQueue::iterator End() {
137 return queue_.end(); 138 return queue_.end();
138 } 139 }
139 140
140 // Returns true if |request| is queued. 141 // Returns true if |request| is queued.
141 bool IsQueued(ScheduledResourceRequest* request) const { 142 bool IsQueued(ScheduledResourceRequestImpl* request) const {
142 return ContainsKey(pointers_, request); 143 return ContainsKey(pointers_, request);
143 } 144 }
144 145
145 // Returns true if no requests are queued. 146 // Returns true if no requests are queued.
146 bool IsEmpty() const { return queue_.size() == 0; } 147 bool IsEmpty() const { return queue_.size() == 0; }
147 148
148 private: 149 private:
149 typedef std::map<ScheduledResourceRequest*, NetQueue::iterator> PointerMap; 150 typedef std::map<ScheduledResourceRequestImpl*, NetQueue::iterator>
151 PointerMap;
150 152
151 uint32 MakeFifoOrderingId() { 153 uint32 MakeFifoOrderingId() {
152 fifo_ordering_ids_ += 1; 154 fifo_ordering_ids_ += 1;
153 return fifo_ordering_ids_; 155 return fifo_ordering_ids_;
154 } 156 }
155 157
156 // Used to create an ordering ID for scheduled resources so that resources 158 // Used to create an ordering ID for scheduled resources so that resources
157 // with same priority/intra_priority stay in fifo order. 159 // with same priority/intra_priority stay in fifo order.
158 uint32 fifo_ordering_ids_; 160 uint32 fifo_ordering_ids_;
159 161
160 NetQueue queue_; 162 NetQueue queue_;
161 PointerMap pointers_; 163 PointerMap pointers_;
162 }; 164 };
163 165
164 // This is the handle we return to the ResourceDispatcherHostImpl so it can 166 // This is the handle we return to the ResourceDispatcherHostImpl so it can
165 // interact with the request. 167 // interact with the request.
166 class ResourceScheduler::ScheduledResourceRequest 168 class ResourceScheduler::ScheduledResourceRequestImpl
167 : public ResourceMessageDelegate, 169 : public ScheduledResourceRequest {
168 public ResourceThrottle {
169 public: 170 public:
170 ScheduledResourceRequest(const ClientId& client_id, 171 ScheduledResourceRequestImpl(const ClientId& client_id,
171 net::URLRequest* request, 172 net::URLRequest* request,
172 ResourceScheduler* scheduler, 173 ResourceScheduler* scheduler,
173 const RequestPriorityParams& priority) 174 const RequestPriorityParams& priority,
174 : ResourceMessageDelegate(request), 175 bool is_async)
175 client_id_(client_id), 176 : client_id_(client_id),
176 client_state_on_creation_(scheduler->GetClientState(client_id_)), 177 client_state_on_creation_(scheduler->GetClientState(client_id_)),
177 request_(request), 178 request_(request),
178 ready_(false), 179 ready_(false),
179 deferred_(false), 180 deferred_(false),
181 is_async_(is_async),
180 classification_(NORMAL_REQUEST), 182 classification_(NORMAL_REQUEST),
181 scheduler_(scheduler), 183 scheduler_(scheduler),
182 priority_(priority), 184 priority_(priority),
183 fifo_ordering_(0) { 185 fifo_ordering_(0) {}
186
187 ~ScheduledResourceRequestImpl() override { scheduler_->RemoveRequest(this); }
188
189 void ChangePriority(net::RequestPriority new_priority,
190 int intra_priority_value) override {
191 scheduler_->ReprioritizeRequest(this, new_priority, intra_priority_value);
184 } 192 }
185 193
186 ~ScheduledResourceRequest() override { scheduler_->RemoveRequest(this); }
187
188 void Start() { 194 void Start() {
189 ready_ = true; 195 ready_ = true;
190 if (!request_->status().is_success()) 196 if (!request_->status().is_success())
191 return; 197 return;
192 base::TimeTicks time = base::TimeTicks::Now(); 198 base::TimeTicks time = base::TimeTicks::Now();
193 ClientState current_state = scheduler_->GetClientState(client_id_); 199 ClientState current_state = scheduler_->GetClientState(client_id_);
194 // Note: the client state isn't perfectly accurate since it won't capture 200 // Note: the client state isn't perfectly accurate since it won't capture
195 // tabs which have switched between active and background multiple times. 201 // tabs which have switched between active and background multiple times.
196 // Ex: A tab with the following transitions Active -> Background -> Active 202 // Ex: A tab with the following transitions Active -> Background -> Active
197 // will be recorded as Active. 203 // will be recorded as Active.
(...skipping 21 matching lines...) Expand all
219 225
220 void set_request_priority_params(const RequestPriorityParams& priority) { 226 void set_request_priority_params(const RequestPriorityParams& priority) {
221 priority_ = priority; 227 priority_ = priority;
222 } 228 }
223 const RequestPriorityParams& get_request_priority_params() const { 229 const RequestPriorityParams& get_request_priority_params() const {
224 return priority_; 230 return priority_;
225 } 231 }
226 const ClientId& client_id() const { return client_id_; } 232 const ClientId& client_id() const { return client_id_; }
227 net::URLRequest* url_request() { return request_; } 233 net::URLRequest* url_request() { return request_; }
228 const net::URLRequest* url_request() const { return request_; } 234 const net::URLRequest* url_request() const { return request_; }
235 bool is_async() const { return is_async_; }
229 uint32 fifo_ordering() const { return fifo_ordering_; } 236 uint32 fifo_ordering() const { return fifo_ordering_; }
230 void set_fifo_ordering(uint32 fifo_ordering) { 237 void set_fifo_ordering(uint32 fifo_ordering) {
231 fifo_ordering_ = fifo_ordering; 238 fifo_ordering_ = fifo_ordering;
232 } 239 }
233 RequestClassification classification() const { 240 RequestClassification classification() const {
234 return classification_; 241 return classification_;
235 } 242 }
236 void set_classification(RequestClassification classification) { 243 void set_classification(RequestClassification classification) {
237 classification_ = classification; 244 classification_ = classification;
238 } 245 }
239 246
240 private: 247 private:
241 // ResourceMessageDelegate interface:
242 bool OnMessageReceived(const IPC::Message& message) override {
243 bool handled = true;
244 IPC_BEGIN_MESSAGE_MAP(ScheduledResourceRequest, message)
245 IPC_MESSAGE_HANDLER(ResourceHostMsg_DidChangePriority, DidChangePriority)
246 IPC_MESSAGE_UNHANDLED(handled = false)
247 IPC_END_MESSAGE_MAP()
248 return handled;
249 }
250
251 // ResourceThrottle interface: 248 // ResourceThrottle interface:
252 void WillStartRequest(bool* defer) override { 249 void WillStartRequest(bool* defer) override {
253 deferred_ = *defer = !ready_; 250 deferred_ = *defer = !ready_;
254 time_deferred_ = base::TimeTicks::Now(); 251 time_deferred_ = base::TimeTicks::Now();
255 } 252 }
256 253
257 const char* GetNameForLogging() const override { return "ResourceScheduler"; } 254 const char* GetNameForLogging() const override { return "ResourceScheduler"; }
258 255
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_; 256 const ClientId client_id_;
265 const ResourceScheduler::ClientState client_state_on_creation_; 257 const ResourceScheduler::ClientState client_state_on_creation_;
266 net::URLRequest* request_; 258 net::URLRequest* request_;
267 bool ready_; 259 bool ready_;
268 bool deferred_; 260 bool deferred_;
261 bool is_async_;
269 RequestClassification classification_; 262 RequestClassification classification_;
270 ResourceScheduler* scheduler_; 263 ResourceScheduler* scheduler_;
271 RequestPriorityParams priority_; 264 RequestPriorityParams priority_;
272 uint32 fifo_ordering_; 265 uint32 fifo_ordering_;
273 base::TimeTicks time_deferred_; 266 base::TimeTicks time_deferred_;
274 267
275 DISALLOW_COPY_AND_ASSIGN(ScheduledResourceRequest); 268 DISALLOW_COPY_AND_ASSIGN(ScheduledResourceRequestImpl);
276 }; 269 };
277 270
278 bool ResourceScheduler::ScheduledResourceSorter::operator()( 271 bool ResourceScheduler::ScheduledResourceSorter::operator()(
279 const ScheduledResourceRequest* a, 272 const ScheduledResourceRequestImpl* a,
280 const ScheduledResourceRequest* b) const { 273 const ScheduledResourceRequestImpl* b) const {
281 // Want the set to be ordered first by decreasing priority, then by 274 // Want the set to be ordered first by decreasing priority, then by
282 // decreasing intra_priority. 275 // decreasing intra_priority.
283 // ie. with (priority, intra_priority) 276 // ie. with (priority, intra_priority)
284 // [(1, 0), (1, 0), (0, 100), (0, 0)] 277 // [(1, 0), (1, 0), (0, 100), (0, 0)]
285 if (a->get_request_priority_params() != b->get_request_priority_params()) 278 if (a->get_request_priority_params() != b->get_request_priority_params())
286 return a->get_request_priority_params().GreaterThan( 279 return a->get_request_priority_params().GreaterThan(
287 b->get_request_priority_params()); 280 b->get_request_priority_params());
288 281
289 // If priority/intra_priority is the same, fall back to fifo ordering. 282 // If priority/intra_priority is the same, fall back to fifo ordering.
290 // std::multiset doesn't guarantee this until c++11. 283 // std::multiset doesn't guarantee this until c++11.
291 return a->fifo_ordering() < b->fifo_ordering(); 284 return a->fifo_ordering() < b->fifo_ordering();
292 } 285 }
293 286
294 void ResourceScheduler::RequestQueue::Insert( 287 void ResourceScheduler::RequestQueue::Insert(
295 ScheduledResourceRequest* request) { 288 ScheduledResourceRequestImpl* request) {
296 DCHECK(!ContainsKey(pointers_, request)); 289 DCHECK(!ContainsKey(pointers_, request));
297 request->set_fifo_ordering(MakeFifoOrderingId()); 290 request->set_fifo_ordering(MakeFifoOrderingId());
298 pointers_[request] = queue_.insert(request); 291 pointers_[request] = queue_.insert(request);
299 } 292 }
300 293
301 // Each client represents a tab. 294 // Each client represents a tab.
302 class ResourceScheduler::Client { 295 class ResourceScheduler::Client {
303 public: 296 public:
304 explicit Client(ResourceScheduler* scheduler, 297 explicit Client(ResourceScheduler* scheduler,
305 bool is_visible, 298 bool is_visible,
(...skipping 12 matching lines...) Expand all
318 311
319 ~Client() { 312 ~Client() {
320 // Update to default state and pause to ensure the scheduler has a 313 // Update to default state and pause to ensure the scheduler has a
321 // correct count of relevant types of clients. 314 // correct count of relevant types of clients.
322 is_visible_ = false; 315 is_visible_ = false;
323 is_audible_ = false; 316 is_audible_ = false;
324 is_paused_ = true; 317 is_paused_ = true;
325 UpdateThrottleState(); 318 UpdateThrottleState();
326 } 319 }
327 320
328 void ScheduleRequest( 321 void ScheduleRequest(net::URLRequest* url_request,
329 net::URLRequest* url_request, 322 ScheduledResourceRequestImpl* request) {
330 ScheduledResourceRequest* request) {
331 if (ShouldStartRequest(request) == START_REQUEST) 323 if (ShouldStartRequest(request) == START_REQUEST)
332 StartRequest(request); 324 StartRequest(request);
333 else 325 else
334 pending_requests_.Insert(request); 326 pending_requests_.Insert(request);
335 SetRequestClassification(request, ClassifyRequest(request)); 327 SetRequestClassification(request, ClassifyRequest(request));
336 } 328 }
337 329
338 void RemoveRequest(ScheduledResourceRequest* request) { 330 void RemoveRequest(ScheduledResourceRequestImpl* request) {
339 if (pending_requests_.IsQueued(request)) { 331 if (pending_requests_.IsQueued(request)) {
340 pending_requests_.Erase(request); 332 pending_requests_.Erase(request);
341 DCHECK(!ContainsKey(in_flight_requests_, request)); 333 DCHECK(!ContainsKey(in_flight_requests_, request));
342 } else { 334 } else {
343 EraseInFlightRequest(request); 335 EraseInFlightRequest(request);
344 336
345 // Removing this request may have freed up another to load. 337 // Removing this request may have freed up another to load.
346 LoadAnyStartablePendingRequests(); 338 LoadAnyStartablePendingRequests();
347 } 339 }
348 } 340 }
349 341
350 RequestSet StartAndRemoveAllRequests() { 342 RequestSet StartAndRemoveAllRequests() {
351 // First start any pending requests so that they will be moved into 343 // First start any pending requests so that they will be moved into
352 // in_flight_requests_. This may exceed the limits 344 // in_flight_requests_. This may exceed the limits
353 // kMaxNumDelayableRequestsPerClient, kMaxNumDelayableRequestsPerHost and 345 // kMaxNumDelayableRequestsPerClient, kMaxNumDelayableRequestsPerHost and
354 // kMaxNumThrottledRequestsPerClient, so this method must not do anything 346 // kMaxNumThrottledRequestsPerClient, so this method must not do anything
355 // that depends on those limits before calling ClearInFlightRequests() 347 // that depends on those limits before calling ClearInFlightRequests()
356 // below. 348 // below.
357 while (!pending_requests_.IsEmpty()) { 349 while (!pending_requests_.IsEmpty()) {
358 ScheduledResourceRequest* request = 350 ScheduledResourceRequestImpl* request =
359 *pending_requests_.GetNextHighestIterator(); 351 *pending_requests_.GetNextHighestIterator();
360 pending_requests_.Erase(request); 352 pending_requests_.Erase(request);
361 // StartRequest() may modify pending_requests_. TODO(ricea): Does it? 353 // StartRequest() may modify pending_requests_. TODO(ricea): Does it?
362 StartRequest(request); 354 StartRequest(request);
363 } 355 }
364 RequestSet unowned_requests; 356 RequestSet unowned_requests;
365 for (RequestSet::iterator it = in_flight_requests_.begin(); 357 for (RequestSet::iterator it = in_flight_requests_.begin();
366 it != in_flight_requests_.end(); ++it) { 358 it != in_flight_requests_.end(); ++it) {
367 unowned_requests.insert(*it); 359 unowned_requests.insert(*it);
368 (*it)->set_classification(NORMAL_REQUEST); 360 (*it)->set_classification(NORMAL_REQUEST);
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
479 LoadAnyStartablePendingRequests(); 471 LoadAnyStartablePendingRequests();
480 } 472 }
481 473
482 void OnReceivedSpdyProxiedHttpResponse() { 474 void OnReceivedSpdyProxiedHttpResponse() {
483 if (!using_spdy_proxy_) { 475 if (!using_spdy_proxy_) {
484 using_spdy_proxy_ = true; 476 using_spdy_proxy_ = true;
485 LoadAnyStartablePendingRequests(); 477 LoadAnyStartablePendingRequests();
486 } 478 }
487 } 479 }
488 480
489 void ReprioritizeRequest(ScheduledResourceRequest* request, 481 void ReprioritizeRequest(ScheduledResourceRequestImpl* request,
490 RequestPriorityParams old_priority_params, 482 RequestPriorityParams old_priority_params,
491 RequestPriorityParams new_priority_params) { 483 RequestPriorityParams new_priority_params) {
492 request->url_request()->SetPriority(new_priority_params.priority); 484 request->url_request()->SetPriority(new_priority_params.priority);
493 request->set_request_priority_params(new_priority_params); 485 request->set_request_priority_params(new_priority_params);
494 if (!pending_requests_.IsQueued(request)) { 486 if (!pending_requests_.IsQueued(request)) {
495 DCHECK(ContainsKey(in_flight_requests_, request)); 487 DCHECK(ContainsKey(in_flight_requests_, request));
496 // The priority of the request and priority support of the server may 488 // The priority of the request and priority support of the server may
497 // have changed, so update the delayable count. 489 // have changed, so update the delayable count.
498 SetRequestClassification(request, ClassifyRequest(request)); 490 SetRequestClassification(request, ClassifyRequest(request));
499 // Request has already started. 491 // Request has already started.
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
553 SetThrottleState(COALESCED); 545 SetThrottleState(COALESCED);
554 } 546 }
555 547
556 private: 548 private:
557 enum ShouldStartReqResult { 549 enum ShouldStartReqResult {
558 DO_NOT_START_REQUEST_AND_STOP_SEARCHING, 550 DO_NOT_START_REQUEST_AND_STOP_SEARCHING,
559 DO_NOT_START_REQUEST_AND_KEEP_SEARCHING, 551 DO_NOT_START_REQUEST_AND_KEEP_SEARCHING,
560 START_REQUEST, 552 START_REQUEST,
561 }; 553 };
562 554
563 void InsertInFlightRequest(ScheduledResourceRequest* request) { 555 void InsertInFlightRequest(ScheduledResourceRequestImpl* request) {
564 in_flight_requests_.insert(request); 556 in_flight_requests_.insert(request);
565 SetRequestClassification(request, ClassifyRequest(request)); 557 SetRequestClassification(request, ClassifyRequest(request));
566 } 558 }
567 559
568 void EraseInFlightRequest(ScheduledResourceRequest* request) { 560 void EraseInFlightRequest(ScheduledResourceRequestImpl* request) {
569 size_t erased = in_flight_requests_.erase(request); 561 size_t erased = in_flight_requests_.erase(request);
570 DCHECK_EQ(1u, erased); 562 DCHECK_EQ(1u, erased);
571 // Clear any special state that we were tracking for this request. 563 // Clear any special state that we were tracking for this request.
572 SetRequestClassification(request, NORMAL_REQUEST); 564 SetRequestClassification(request, NORMAL_REQUEST);
573 } 565 }
574 566
575 void ClearInFlightRequests() { 567 void ClearInFlightRequests() {
576 in_flight_requests_.clear(); 568 in_flight_requests_.clear();
577 in_flight_delayable_count_ = 0; 569 in_flight_delayable_count_ = 0;
578 total_layout_blocking_count_ = 0; 570 total_layout_blocking_count_ = 0;
(...skipping 11 matching lines...) Expand all
590 for (RequestQueue::NetQueue::const_iterator 582 for (RequestQueue::NetQueue::const_iterator
591 it = pending_requests_.GetNextHighestIterator(); 583 it = pending_requests_.GetNextHighestIterator();
592 it != pending_requests_.End(); ++it) { 584 it != pending_requests_.End(); ++it) {
593 if ((*it)->classification() == classification) 585 if ((*it)->classification() == classification)
594 classification_request_count++; 586 classification_request_count++;
595 } 587 }
596 } 588 }
597 return classification_request_count; 589 return classification_request_count;
598 } 590 }
599 591
600 void SetRequestClassification(ScheduledResourceRequest* request, 592 void SetRequestClassification(ScheduledResourceRequestImpl* request,
601 RequestClassification classification) { 593 RequestClassification classification) {
602 RequestClassification old_classification = request->classification(); 594 RequestClassification old_classification = request->classification();
603 if (old_classification == classification) 595 if (old_classification == classification)
604 return; 596 return;
605 597
606 if (old_classification == IN_FLIGHT_DELAYABLE_REQUEST) 598 if (old_classification == IN_FLIGHT_DELAYABLE_REQUEST)
607 in_flight_delayable_count_--; 599 in_flight_delayable_count_--;
608 if (old_classification == LAYOUT_BLOCKING_REQUEST) 600 if (old_classification == LAYOUT_BLOCKING_REQUEST)
609 total_layout_blocking_count_--; 601 total_layout_blocking_count_--;
610 602
611 if (classification == IN_FLIGHT_DELAYABLE_REQUEST) 603 if (classification == IN_FLIGHT_DELAYABLE_REQUEST)
612 in_flight_delayable_count_++; 604 in_flight_delayable_count_++;
613 if (classification == LAYOUT_BLOCKING_REQUEST) 605 if (classification == LAYOUT_BLOCKING_REQUEST)
614 total_layout_blocking_count_++; 606 total_layout_blocking_count_++;
615 607
616 request->set_classification(classification); 608 request->set_classification(classification);
617 DCHECK_EQ( 609 DCHECK_EQ(
618 CountRequestsWithClassification(IN_FLIGHT_DELAYABLE_REQUEST, false), 610 CountRequestsWithClassification(IN_FLIGHT_DELAYABLE_REQUEST, false),
619 in_flight_delayable_count_); 611 in_flight_delayable_count_);
620 DCHECK_EQ(CountRequestsWithClassification(LAYOUT_BLOCKING_REQUEST, true), 612 DCHECK_EQ(CountRequestsWithClassification(LAYOUT_BLOCKING_REQUEST, true),
621 total_layout_blocking_count_); 613 total_layout_blocking_count_);
622 } 614 }
623 615
624 RequestClassification ClassifyRequest(ScheduledResourceRequest* request) { 616 RequestClassification ClassifyRequest(ScheduledResourceRequestImpl* request) {
625 // If a request is already marked as layout-blocking make sure to keep the 617 // If a request is already marked as layout-blocking make sure to keep the
626 // classification across redirects unless the priority was lowered. 618 // classification across redirects unless the priority was lowered.
627 if (request->classification() == LAYOUT_BLOCKING_REQUEST && 619 if (request->classification() == LAYOUT_BLOCKING_REQUEST &&
628 request->url_request()->priority() > net::LOW) { 620 request->url_request()->priority() > net::LOW) {
629 return LAYOUT_BLOCKING_REQUEST; 621 return LAYOUT_BLOCKING_REQUEST;
630 } 622 }
631 623
632 if (!has_body_ && request->url_request()->priority() > net::LOW) 624 if (!has_body_ && request->url_request()->priority() > net::LOW)
633 return LAYOUT_BLOCKING_REQUEST; 625 return LAYOUT_BLOCKING_REQUEST;
634 626
(...skipping 19 matching lines...) Expand all
654 net::HostPortPair::FromURL((*it)->url_request()->url()); 646 net::HostPortPair::FromURL((*it)->url_request()->url());
655 if (active_request_host.Equals(host_port_pair)) { 647 if (active_request_host.Equals(host_port_pair)) {
656 same_host_count++; 648 same_host_count++;
657 if (same_host_count >= kMaxNumDelayableRequestsPerHost) 649 if (same_host_count >= kMaxNumDelayableRequestsPerHost)
658 return true; 650 return true;
659 } 651 }
660 } 652 }
661 return false; 653 return false;
662 } 654 }
663 655
664 void StartRequest(ScheduledResourceRequest* request) { 656 void StartRequest(ScheduledResourceRequestImpl* request) {
665 InsertInFlightRequest(request); 657 InsertInFlightRequest(request);
666 request->Start(); 658 request->Start();
667 } 659 }
668 660
669 // ShouldStartRequest is the main scheduling algorithm. 661 // ShouldStartRequest is the main scheduling algorithm.
670 // 662 //
671 // Requests are evaluated on five attributes: 663 // Requests are evaluated on five attributes:
672 // 664 //
673 // 1. Non-delayable requests: 665 // 1. Non-delayable requests:
674 // * Synchronous requests. 666 // * 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 704 // * If no high priority requests are in flight, start loading low priority
713 // requests. 705 // requests.
714 // 706 //
715 // COALESCED Clients never load requests, with the following exceptions: 707 // COALESCED Clients never load requests, with the following exceptions:
716 // * Non-delayable requests are issued imediately. 708 // * Non-delayable requests are issued imediately.
717 // * On a (currently 5 second) heart beat, they load all requests as an 709 // * On a (currently 5 second) heart beat, they load all requests as an
718 // UNTHROTTLED Client, and then return to the COALESCED state. 710 // UNTHROTTLED Client, and then return to the COALESCED state.
719 // * When an active Client makes a request, they are THROTTLED until the 711 // * When an active Client makes a request, they are THROTTLED until the
720 // active Client finishes loading. 712 // active Client finishes loading.
721 ShouldStartReqResult ShouldStartRequest( 713 ShouldStartReqResult ShouldStartRequest(
722 ScheduledResourceRequest* request) const { 714 ScheduledResourceRequestImpl* request) const {
723 const net::URLRequest& url_request = *request->url_request(); 715 const net::URLRequest& url_request = *request->url_request();
724 // Syncronous requests could block the entire render, which could impact 716 // Syncronous requests could block the entire render, which could impact
725 // user-observable Clients. 717 // user-observable Clients.
726 if (!ResourceRequestInfo::ForRequest(&url_request)->IsAsync()) { 718 if (!request->is_async()) {
727 return START_REQUEST; 719 return START_REQUEST;
728 } 720 }
729 721
730 // TODO(simonjam): This may end up causing disk contention. We should 722 // TODO(simonjam): This may end up causing disk contention. We should
731 // experiment with throttling if that happens. 723 // experiment with throttling if that happens.
732 // TODO(aiolos): We probably want to Coalesce these as well to avoid 724 // TODO(aiolos): We probably want to Coalesce these as well to avoid
733 // waking the disk. 725 // waking the disk.
734 if (!url_request.url().SchemeIsHTTPOrHTTPS()) { 726 if (!url_request.url().SchemeIsHTTPOrHTTPS()) {
735 return START_REQUEST; 727 return START_REQUEST;
736 } 728 }
(...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. 795 // 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 796 // 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 797 // there may be room for other requests, so we keep checking and leave
806 // the previous request still in the list. 798 // the previous request still in the list.
807 // 3) We do not start the request, same as above, but StartRequest() tells 799 // 3) We do not start the request, same as above, but StartRequest() tells
808 // us there's no point in checking any further requests. 800 // us there's no point in checking any further requests.
809 RequestQueue::NetQueue::iterator request_iter = 801 RequestQueue::NetQueue::iterator request_iter =
810 pending_requests_.GetNextHighestIterator(); 802 pending_requests_.GetNextHighestIterator();
811 803
812 while (request_iter != pending_requests_.End()) { 804 while (request_iter != pending_requests_.End()) {
813 ScheduledResourceRequest* request = *request_iter; 805 ScheduledResourceRequestImpl* request = *request_iter;
814 ShouldStartReqResult query_result = ShouldStartRequest(request); 806 ShouldStartReqResult query_result = ShouldStartRequest(request);
815 807
816 if (query_result == START_REQUEST) { 808 if (query_result == START_REQUEST) {
817 pending_requests_.Erase(request); 809 pending_requests_.Erase(request);
818 StartRequest(request); 810 StartRequest(request);
819 811
820 // StartRequest can modify the pending list, so we (re)start evaluation 812 // StartRequest can modify the pending list, so we (re)start evaluation
821 // from the currently highest priority request. Avoid copying a singular 813 // from the currently highest priority request. Avoid copying a singular
822 // iterator, which would trigger undefined behavior. 814 // iterator, which would trigger undefined behavior.
823 if (pending_requests_.GetNextHighestIterator() == 815 if (pending_requests_.GetNextHighestIterator() ==
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
898 OnLoadingActiveClientsStateChangedForAllClients(); 890 OnLoadingActiveClientsStateChangedForAllClients();
899 } 891 }
900 892
901 ResourceScheduler::ClientThrottleState 893 ResourceScheduler::ClientThrottleState
902 ResourceScheduler::GetClientStateForTesting(int child_id, int route_id) { 894 ResourceScheduler::GetClientStateForTesting(int child_id, int route_id) {
903 Client* client = GetClient(child_id, route_id); 895 Client* client = GetClient(child_id, route_id);
904 DCHECK(client); 896 DCHECK(client);
905 return client->throttle_state(); 897 return client->throttle_state();
906 } 898 }
907 899
908 scoped_ptr<ResourceThrottle> ResourceScheduler::ScheduleRequest( 900 scoped_ptr<ScheduledResourceRequest> ResourceScheduler::ScheduleRequest(
909 int child_id, 901 int child_id,
910 int route_id, 902 int route_id,
903 bool is_async,
911 net::URLRequest* url_request) { 904 net::URLRequest* url_request) {
912 DCHECK(CalledOnValidThread()); 905 DCHECK(CalledOnValidThread());
913 ClientId client_id = MakeClientId(child_id, route_id); 906 ClientId client_id = MakeClientId(child_id, route_id);
914 scoped_ptr<ScheduledResourceRequest> request(new ScheduledResourceRequest( 907 scoped_ptr<ScheduledResourceRequestImpl> request(
915 client_id, 908 new ScheduledResourceRequestImpl(
916 url_request, 909 client_id, url_request, this,
917 this, 910 RequestPriorityParams(url_request->priority(), 0), is_async));
918 RequestPriorityParams(url_request->priority(), 0)));
919 911
920 ClientMap::iterator it = client_map_.find(client_id); 912 ClientMap::iterator it = client_map_.find(client_id);
921 if (it == client_map_.end()) { 913 if (it == client_map_.end()) {
922 // There are several ways this could happen: 914 // There are several ways this could happen:
923 // 1. <a ping> requests don't have a route_id. 915 // 1. <a ping> requests don't have a route_id.
924 // 2. Most unittests don't send the IPCs needed to register Clients. 916 // 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. 917 // 3. The tab is closed while a RequestResource IPC is in flight.
926 unowned_requests_.insert(request.get()); 918 unowned_requests_.insert(request.get());
927 request->Start(); 919 request->Start();
928 return request.Pass(); 920 return request.Pass();
929 } 921 }
930 922
931 Client* client = it->second; 923 Client* client = it->second;
932 client->ScheduleRequest(url_request, request.get()); 924 client->ScheduleRequest(url_request, request.get());
933 return request.Pass(); 925 return request.Pass();
934 } 926 }
935 927
936 void ResourceScheduler::RemoveRequest(ScheduledResourceRequest* request) { 928 void ResourceScheduler::RemoveRequest(ScheduledResourceRequestImpl* request) {
937 DCHECK(CalledOnValidThread()); 929 DCHECK(CalledOnValidThread());
938 if (ContainsKey(unowned_requests_, request)) { 930 if (ContainsKey(unowned_requests_, request)) {
939 unowned_requests_.erase(request); 931 unowned_requests_.erase(request);
940 return; 932 return;
941 } 933 }
942 934
943 ClientMap::iterator client_it = client_map_.find(request->client_id()); 935 ClientMap::iterator client_it = client_map_.find(request->client_id());
944 if (client_it == client_map_.end()) { 936 if (client_it == client_map_.end()) {
945 return; 937 return;
946 } 938 }
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after
1164 } 1156 }
1165 1157
1166 ResourceScheduler::ClientState ResourceScheduler::GetClientState( 1158 ResourceScheduler::ClientState ResourceScheduler::GetClientState(
1167 ClientId client_id) const { 1159 ClientId client_id) const {
1168 ClientMap::const_iterator client_it = client_map_.find(client_id); 1160 ClientMap::const_iterator client_it = client_map_.find(client_id);
1169 if (client_it == client_map_.end()) 1161 if (client_it == client_map_.end())
1170 return UNKNOWN; 1162 return UNKNOWN;
1171 return client_it->second->is_active() ? ACTIVE : BACKGROUND; 1163 return client_it->second->is_active() ? ACTIVE : BACKGROUND;
1172 } 1164 }
1173 1165
1174 void ResourceScheduler::ReprioritizeRequest(ScheduledResourceRequest* request, 1166 void ResourceScheduler::ReprioritizeRequest(
1175 net::RequestPriority new_priority, 1167 ScheduledResourceRequestImpl* request,
1176 int new_intra_priority_value) { 1168 net::RequestPriority new_priority,
1169 int new_intra_priority_value) {
1177 if (request->url_request()->load_flags() & net::LOAD_IGNORE_LIMITS) { 1170 if (request->url_request()->load_flags() & net::LOAD_IGNORE_LIMITS) {
1178 // We should not be re-prioritizing requests with the 1171 // We should not be re-prioritizing requests with the
1179 // IGNORE_LIMITS flag. 1172 // IGNORE_LIMITS flag.
1180 NOTREACHED(); 1173 NOTREACHED();
1181 return; 1174 return;
1182 } 1175 }
1183 RequestPriorityParams new_priority_params(new_priority, 1176 RequestPriorityParams new_priority_params(new_priority,
1184 new_intra_priority_value); 1177 new_intra_priority_value);
1185 RequestPriorityParams old_priority_params = 1178 RequestPriorityParams old_priority_params =
1186 request->get_request_priority_params(); 1179 request->get_request_priority_params();
(...skipping 15 matching lines...) Expand all
1202 client->ReprioritizeRequest( 1195 client->ReprioritizeRequest(
1203 request, old_priority_params, new_priority_params); 1196 request, old_priority_params, new_priority_params);
1204 } 1197 }
1205 1198
1206 ResourceScheduler::ClientId ResourceScheduler::MakeClientId( 1199 ResourceScheduler::ClientId ResourceScheduler::MakeClientId(
1207 int child_id, int route_id) { 1200 int child_id, int route_id) {
1208 return (static_cast<ResourceScheduler::ClientId>(child_id) << 32) | route_id; 1201 return (static_cast<ResourceScheduler::ClientId>(child_id) << 32) | route_id;
1209 } 1202 }
1210 1203
1211 } // namespace content 1204 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698