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

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

Issue 180843016: Cache total_delayable_count for in_flight_requests in ResourceScheduler (Closed) Base URL: https://git.chromium.org/chromium/src.git@master
Patch Set: Created 6 years, 9 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
« AUTHORS ('K') | « content/browser/loader/resource_scheduler.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "content/browser/loader/resource_scheduler.h" 5 #include "content/browser/loader/resource_scheduler.h"
6 6
7 #include "base/stl_util.h" 7 #include "base/stl_util.h"
8 #include "content/common/resource_messages.h" 8 #include "content/common/resource_messages.h"
9 #include "content/browser/loader/resource_message_delegate.h" 9 #include "content/browser/loader/resource_message_delegate.h"
10 #include "content/public/browser/resource_controller.h" 10 #include "content/public/browser/resource_controller.h"
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
170 ClientId client_id_; 170 ClientId client_id_;
171 net::URLRequest* request_; 171 net::URLRequest* request_;
172 bool ready_; 172 bool ready_;
173 bool deferred_; 173 bool deferred_;
174 ResourceScheduler* scheduler_; 174 ResourceScheduler* scheduler_;
175 175
176 DISALLOW_COPY_AND_ASSIGN(ScheduledResourceRequest); 176 DISALLOW_COPY_AND_ASSIGN(ScheduledResourceRequest);
177 }; 177 };
178 178
179 // Each client represents a tab. 179 // Each client represents a tab.
180 struct ResourceScheduler::Client { 180 struct ResourceScheduler::Client {
James Simonsen 2014/03/05 02:30:59 This isn't a struct anymore. To keep these methods
181 Client() : has_body(false), using_spdy_proxy(false) {} 181 Client()
182 : has_body(false),
183 using_spdy_proxy(false),
184 total_delayable_count(0) {}
182 ~Client() {} 185 ~Client() {}
183 186
184 bool has_body; 187 bool has_body;
185 bool using_spdy_proxy; 188 bool using_spdy_proxy;
186 RequestQueue pending_requests; 189 RequestQueue pending_requests;
187 RequestSet in_flight_requests; 190 RequestSet in_flight_requests;
191 size_t total_delayable_count;
192
193 bool IsDelayableRequest(ScheduledResourceRequest* request) {
194 if (request->url_request()->priority() < net::LOW) {
195 net::HostPortPair host_port_pair =
196 net::HostPortPair::FromURL(request->url_request()->url());
197 const net::HttpServerProperties& http_server_properties =
198 *request->url_request()->context()->http_server_properties();
199 if (!http_server_properties.SupportsSpdy(host_port_pair)) {
200 return true;
201 }
202 }
203 return false;
204 }
205
206 void InsertFlightRequests(ScheduledResourceRequest* request) {
James Simonsen 2014/03/05 02:30:59 This should be InsertInFlightRequest().
207 in_flight_requests.insert(request);
208 if (IsDelayableRequest(request))
209 total_delayable_count++;
210 }
211
212 size_t EraseFlightRequests(ScheduledResourceRequest* request) {
James Simonsen 2014/03/05 02:30:59 And EraseInFlightRequest().
213 size_t erased = in_flight_requests.erase(request);
214 if (in_flight_requests.size() == 0) {
215 total_delayable_count = 0;
216 } else if (IsDelayableRequest(request)) {
217 total_delayable_count--;
218 }
219 return erased;
220 }
221
222 void ClearFlightRequests() {
James Simonsen 2014/03/05 02:30:59 ClearInFlightRequests()
223 in_flight_requests.clear();
224 total_delayable_count = 0;
225 }
188 }; 226 };
189 227
190 ResourceScheduler::ResourceScheduler() { 228 ResourceScheduler::ResourceScheduler() {
191 } 229 }
192 230
193 ResourceScheduler::~ResourceScheduler() { 231 ResourceScheduler::~ResourceScheduler() {
194 DCHECK(unowned_requests_.empty()); 232 DCHECK(unowned_requests_.empty());
195 DCHECK(client_map_.empty()); 233 DCHECK(client_map_.empty());
196 } 234 }
197 235
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
235 if (client_it == client_map_.end()) { 273 if (client_it == client_map_.end()) {
236 return; 274 return;
237 } 275 }
238 276
239 Client* client = client_it->second; 277 Client* client = client_it->second;
240 278
241 if (client->pending_requests.IsQueued(request)) { 279 if (client->pending_requests.IsQueued(request)) {
242 client->pending_requests.Erase(request); 280 client->pending_requests.Erase(request);
243 DCHECK(!ContainsKey(client->in_flight_requests, request)); 281 DCHECK(!ContainsKey(client->in_flight_requests, request));
244 } else { 282 } else {
245 size_t erased = client->in_flight_requests.erase(request); 283 size_t erased = client->EraseFlightRequests(request);
246 DCHECK(erased); 284 DCHECK(erased);
247 285
248 // Removing this request may have freed up another to load. 286 // Removing this request may have freed up another to load.
249 LoadAnyStartablePendingRequests(client); 287 LoadAnyStartablePendingRequests(client);
250 } 288 }
251 } 289 }
252 290
253 void ResourceScheduler::OnClientCreated(int child_id, int route_id) { 291 void ResourceScheduler::OnClientCreated(int child_id, int route_id) {
254 DCHECK(CalledOnValidThread()); 292 DCHECK(CalledOnValidThread());
255 ClientId client_id = MakeClientId(child_id, route_id); 293 ClientId client_id = MakeClientId(child_id, route_id);
(...skipping 12 matching lines...) Expand all
268 306
269 Client* client = it->second; 307 Client* client = it->second;
270 308
271 // FYI, ResourceDispatcherHost cancels all of the requests after this function 309 // FYI, ResourceDispatcherHost cancels all of the requests after this function
272 // is called. It should end up canceling all of the requests except for a 310 // is called. It should end up canceling all of the requests except for a
273 // cross-renderer navigation. 311 // cross-renderer navigation.
274 for (RequestSet::iterator it = client->in_flight_requests.begin(); 312 for (RequestSet::iterator it = client->in_flight_requests.begin();
275 it != client->in_flight_requests.end(); ++it) { 313 it != client->in_flight_requests.end(); ++it) {
276 unowned_requests_.insert(*it); 314 unowned_requests_.insert(*it);
277 } 315 }
278 client->in_flight_requests.clear(); 316 client->ClearFlightRequests();
279 317
280 delete client; 318 delete client;
281 client_map_.erase(it); 319 client_map_.erase(it);
282 } 320 }
283 321
284 void ResourceScheduler::OnNavigate(int child_id, int route_id) { 322 void ResourceScheduler::OnNavigate(int child_id, int route_id) {
285 DCHECK(CalledOnValidThread()); 323 DCHECK(CalledOnValidThread());
286 ClientId client_id = MakeClientId(child_id, route_id); 324 ClientId client_id = MakeClientId(child_id, route_id);
287 325
288 ClientMap::iterator it = client_map_.find(client_id); 326 ClientMap::iterator it = client_map_.find(client_id);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
324 Client* client = client_it->second; 362 Client* client = client_it->second;
325 363
326 if (!client->using_spdy_proxy) { 364 if (!client->using_spdy_proxy) {
327 client->using_spdy_proxy = true; 365 client->using_spdy_proxy = true;
328 LoadAnyStartablePendingRequests(client); 366 LoadAnyStartablePendingRequests(client);
329 } 367 }
330 } 368 }
331 369
332 void ResourceScheduler::StartRequest(ScheduledResourceRequest* request, 370 void ResourceScheduler::StartRequest(ScheduledResourceRequest* request,
333 Client* client) { 371 Client* client) {
334 client->in_flight_requests.insert(request); 372 client->InsertFlightRequests(request);
335 request->Start(); 373 request->Start();
336 } 374 }
337 375
338 void ResourceScheduler::ReprioritizeRequest(ScheduledResourceRequest* request, 376 void ResourceScheduler::ReprioritizeRequest(ScheduledResourceRequest* request,
339 net::RequestPriority new_priority) { 377 net::RequestPriority new_priority) {
340 if (request->url_request()->load_flags() & net::LOAD_IGNORE_LIMITS) { 378 if (request->url_request()->load_flags() & net::LOAD_IGNORE_LIMITS) {
341 // We should not be re-prioritizing requests with the 379 // We should not be re-prioritizing requests with the
342 // IGNORE_LIMITS flag. 380 // IGNORE_LIMITS flag.
343 NOTREACHED(); 381 NOTREACHED();
344 return; 382 return;
345 } 383 }
346 net::RequestPriority old_priority = request->url_request()->priority(); 384 net::RequestPriority old_priority = request->url_request()->priority();
347 DCHECK_NE(new_priority, old_priority); 385 DCHECK_NE(new_priority, old_priority);
348 request->url_request()->SetPriority(new_priority); 386 request->url_request()->SetPriority(new_priority);
349 ClientMap::iterator client_it = client_map_.find(request->client_id()); 387 ClientMap::iterator client_it = client_map_.find(request->client_id());
350 if (client_it == client_map_.end()) { 388 if (client_it == client_map_.end()) {
351 // The client was likely deleted shortly before we received this IPC. 389 // The client was likely deleted shortly before we received this IPC.
352 return; 390 return;
353 } 391 }
354 392
355 Client *client = client_it->second; 393 Client *client = client_it->second;
356 if (!client->pending_requests.IsQueued(request)) { 394 if (!client->pending_requests.IsQueued(request)) {
357 DCHECK(ContainsKey(client->in_flight_requests, request)); 395 DCHECK(ContainsKey(client->in_flight_requests, request));
396 if (new_priority >= net::LOW) {
397 if (client->IsDelayableRequest(request))
398 client->total_delayable_count--;
James Simonsen 2014/03/05 02:30:59 Please add a unit test that shows the old code was
James Simonsen 2014/03/05 02:30:59 I don't like that total_delayable_count is sometim
399 }
358 // Request has already started. 400 // Request has already started.
359 return; 401 return;
360 } 402 }
361 403
362 client->pending_requests.Erase(request); 404 client->pending_requests.Erase(request);
363 client->pending_requests.Insert(request, 405 client->pending_requests.Insert(request,
364 request->url_request()->priority()); 406 request->url_request()->priority());
365 407
366 if (new_priority > old_priority) { 408 if (new_priority > old_priority) {
367 // Check if this request is now able to load at its new priority. 409 // Check if this request is now able to load at its new priority.
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
399 } else if (query_result == DO_NOT_START_REQUEST_AND_KEEP_SEARCHING) { 441 } else if (query_result == DO_NOT_START_REQUEST_AND_KEEP_SEARCHING) {
400 ++request_iter; 442 ++request_iter;
401 continue; 443 continue;
402 } else { 444 } else {
403 DCHECK(query_result == DO_NOT_START_REQUEST_AND_STOP_SEARCHING); 445 DCHECK(query_result == DO_NOT_START_REQUEST_AND_STOP_SEARCHING);
404 break; 446 break;
405 } 447 }
406 } 448 }
407 } 449 }
408 450
409 void ResourceScheduler::GetNumDelayableRequestsInFlight( 451 size_t ResourceScheduler::GetNumSameHostRequestsInFlight(
410 Client* client, 452 Client* client,
411 const net::HostPortPair& active_request_host, 453 const net::HostPortPair& active_request_host) const {
412 size_t* total_delayable, 454 DCHECK(client != NULL);
413 size_t* total_for_active_host) const {
414 DCHECK(client != NULL && total_delayable != NULL &&
415 total_for_active_host != NULL);
416 455
417 size_t total_delayable_count = 0;
418 size_t same_host_count = 0; 456 size_t same_host_count = 0;
419 for (RequestSet::iterator it = client->in_flight_requests.begin(); 457 for (RequestSet::iterator it = client->in_flight_requests.begin();
420 it != client->in_flight_requests.end(); ++it) { 458 it != client->in_flight_requests.end(); ++it) {
421 net::HostPortPair host_port_pair = 459 net::HostPortPair host_port_pair =
422 net::HostPortPair::FromURL((*it)->url_request()->url()); 460 net::HostPortPair::FromURL((*it)->url_request()->url());
423 461
424 if (active_request_host.Equals(host_port_pair)) { 462 if (active_request_host.Equals(host_port_pair)) {
425 same_host_count++; 463 same_host_count++;
426 } 464 }
427
428 if ((*it)->url_request()->priority() < net::LOW) {
429 const net::HttpServerProperties& http_server_properties =
430 *(*it)->url_request()->context()->http_server_properties();
431
432 if (!http_server_properties.SupportsSpdy(host_port_pair)) {
433 ++total_delayable_count;
434 }
435 }
436 } 465 }
437 *total_delayable = total_delayable_count; 466 return same_host_count;
438 *total_for_active_host = same_host_count;
439 } 467 }
440 468
441 // ShouldStartRequest is the main scheduling algorithm. 469 // ShouldStartRequest is the main scheduling algorithm.
442 // 470 //
443 // Requests are categorized into two categories: 471 // Requests are categorized into two categories:
444 // 472 //
445 // 1. Immediately issued requests, which are: 473 // 1. Immediately issued requests, which are:
446 // 474 //
447 // * Higher priority requests (>= net::LOW). 475 // * Higher priority requests (>= net::LOW).
448 // * Synchronous requests. 476 // * Synchronous requests.
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
483 net::HostPortPair host_port_pair = 511 net::HostPortPair host_port_pair =
484 net::HostPortPair::FromURL(url_request.url()); 512 net::HostPortPair::FromURL(url_request.url());
485 513
486 // TODO(willchan): We should really improve this algorithm as described in 514 // TODO(willchan): We should really improve this algorithm as described in
487 // crbug.com/164101. Also, theoretically we should not count a SPDY request 515 // crbug.com/164101. Also, theoretically we should not count a SPDY request
488 // against the delayable requests limit. 516 // against the delayable requests limit.
489 if (http_server_properties.SupportsSpdy(host_port_pair)) { 517 if (http_server_properties.SupportsSpdy(host_port_pair)) {
490 return START_REQUEST; 518 return START_REQUEST;
491 } 519 }
492 520
493 size_t num_delayable_requests_in_flight = 0; 521 size_t num_delayable_requests_in_flight = client->total_delayable_count;
494 size_t num_requests_in_flight_for_host = 0; 522 size_t num_requests_in_flight_for_host =
495 GetNumDelayableRequestsInFlight(client, host_port_pair, 523 GetNumSameHostRequestsInFlight(client, host_port_pair);
496 &num_delayable_requests_in_flight,
497 &num_requests_in_flight_for_host);
498 524
499 if (num_delayable_requests_in_flight >= kMaxNumDelayableRequestsPerClient) { 525 if (num_delayable_requests_in_flight >= kMaxNumDelayableRequestsPerClient) {
500 return DO_NOT_START_REQUEST_AND_STOP_SEARCHING; 526 return DO_NOT_START_REQUEST_AND_STOP_SEARCHING;
501 } 527 }
502 528
503 if (num_requests_in_flight_for_host >= kMaxNumDelayableRequestsPerHost) { 529 if (num_requests_in_flight_for_host >= kMaxNumDelayableRequestsPerHost) {
504 // There may be other requests for other hosts we'd allow, so keep checking. 530 // There may be other requests for other hosts we'd allow, so keep checking.
505 return DO_NOT_START_REQUEST_AND_KEEP_SEARCHING; 531 return DO_NOT_START_REQUEST_AND_KEEP_SEARCHING;
506 } 532 }
507 533
508 bool have_immediate_requests_in_flight = 534 bool have_immediate_requests_in_flight =
509 client->in_flight_requests.size() > num_delayable_requests_in_flight; 535 client->in_flight_requests.size() > num_delayable_requests_in_flight;
510 if (have_immediate_requests_in_flight && !client->has_body && 536 if (have_immediate_requests_in_flight && !client->has_body &&
511 num_delayable_requests_in_flight != 0) { 537 num_delayable_requests_in_flight != 0) {
512 return DO_NOT_START_REQUEST_AND_STOP_SEARCHING; 538 return DO_NOT_START_REQUEST_AND_STOP_SEARCHING;
513 } 539 }
514 540
515 return START_REQUEST; 541 return START_REQUEST;
516 } 542 }
517 543
518 ResourceScheduler::ClientId ResourceScheduler::MakeClientId( 544 ResourceScheduler::ClientId ResourceScheduler::MakeClientId(
519 int child_id, int route_id) { 545 int child_id, int route_id) {
520 return (static_cast<ResourceScheduler::ClientId>(child_id) << 32) | route_id; 546 return (static_cast<ResourceScheduler::ClientId>(child_id) << 32) | route_id;
521 } 547 }
522 548
523 } // namespace content 549 } // namespace content
OLDNEW
« AUTHORS ('K') | « content/browser/loader/resource_scheduler.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698