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

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

Issue 2579933002: Add logging for ResourceScheduler events. (Closed)
Patch Set: DCHECK to make sure that all async starts have defined triggers. Created 3 years, 11 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 "content/browser/loader/resource_scheduler.h" 5 #include "content/browser/loader/resource_scheduler.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 #include <set> 8 #include <set>
9 #include <string> 9 #include <string>
10 #include <utility> 10 #include <utility>
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
44 }; 44 };
45 45
46 // Flags identifying various attributes of the request that are used 46 // Flags identifying various attributes of the request that are used
47 // when making scheduling decisions. 47 // when making scheduling decisions.
48 using RequestAttributes = uint8_t; 48 using RequestAttributes = uint8_t;
49 const RequestAttributes kAttributeNone = 0x00; 49 const RequestAttributes kAttributeNone = 0x00;
50 const RequestAttributes kAttributeInFlight = 0x01; 50 const RequestAttributes kAttributeInFlight = 0x01;
51 const RequestAttributes kAttributeDelayable = 0x02; 51 const RequestAttributes kAttributeDelayable = 0x02;
52 const RequestAttributes kAttributeLayoutBlocking = 0x04; 52 const RequestAttributes kAttributeLayoutBlocking = 0x04;
53 53
54 // Reasons why pending requests may be started. For logging only.
55 enum class RequestStartTrigger {
56 NONE,
57 COMPLETION_PRE_BODY,
58 COMPLETION_POST_BODY,
59 BODY_REACHED,
60 CLIENT_KILL,
61 SPDY_PROXY_DETECTED,
62 REQUEST_REPRIORITIZED,
63 };
64
65 const char* RequestStartTriggerString(RequestStartTrigger trigger) {
66 switch (trigger) {
67 case RequestStartTrigger::NONE:
68 return "NONE";
69 case RequestStartTrigger::COMPLETION_PRE_BODY:
70 return "COMPLETION_PRE_BODY";
71 case RequestStartTrigger::COMPLETION_POST_BODY:
72 return "COMPLETION_POST_BODY";
73 case RequestStartTrigger::BODY_REACHED:
74 return "BODY_REACHED";
75 case RequestStartTrigger::CLIENT_KILL:
76 return "CLIENT_KILL";
77 case RequestStartTrigger::SPDY_PROXY_DETECTED:
78 return "SPDY_PROXY_DETECTED";
79 case RequestStartTrigger::REQUEST_REPRIORITIZED:
80 return "REQUEST_REPRIORITIZED";
81 }
82 NOTREACHED();
83 return "Unknown";
84 }
85
54 } // namespace 86 } // namespace
55 87
56 // The maximum number of delayable requests to allow to be in-flight at any 88 // The maximum number of delayable requests to allow to be in-flight at any
57 // point in time (across all hosts). 89 // point in time (across all hosts).
58 static const size_t kMaxNumDelayableRequestsPerClient = 10; 90 static const size_t kMaxNumDelayableRequestsPerClient = 10;
59 91
60 // The maximum number of requests to allow be in-flight at any point in time per 92 // The maximum number of requests to allow be in-flight at any point in time per
61 // host. 93 // host.
62 static const size_t kMaxNumDelayableRequestsPerHostPerClient = 6; 94 static const size_t kMaxNumDelayableRequestsPerHostPerClient = 6;
63 95
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after
323 total_layout_blocking_count_(0), 355 total_layout_blocking_count_(0),
324 priority_requests_delayable_(priority_requests_delayable) {} 356 priority_requests_delayable_(priority_requests_delayable) {}
325 357
326 ~Client() {} 358 ~Client() {}
327 359
328 void ScheduleRequest(net::URLRequest* url_request, 360 void ScheduleRequest(net::URLRequest* url_request,
329 ScheduledResourceRequest* request) { 361 ScheduledResourceRequest* request) {
330 SetRequestAttributes(request, DetermineRequestAttributes(request)); 362 SetRequestAttributes(request, DetermineRequestAttributes(request));
331 if (ShouldStartRequest(request) == START_REQUEST) { 363 if (ShouldStartRequest(request) == START_REQUEST) {
332 // New requests can be started synchronously without issue. 364 // New requests can be started synchronously without issue.
333 StartRequest(request, START_SYNC); 365 StartRequest(request, START_SYNC, RequestStartTrigger::NONE);
334 } else { 366 } else {
335 pending_requests_.Insert(request); 367 pending_requests_.Insert(request);
336 } 368 }
337 } 369 }
338 370
339 void RemoveRequest(ScheduledResourceRequest* request) { 371 void RemoveRequest(ScheduledResourceRequest* request) {
340 if (pending_requests_.IsQueued(request)) { 372 if (pending_requests_.IsQueued(request)) {
341 pending_requests_.Erase(request); 373 pending_requests_.Erase(request);
342 DCHECK(!base::ContainsKey(in_flight_requests_, request)); 374 DCHECK(!base::ContainsKey(in_flight_requests_, request));
343 } else { 375 } else {
344 EraseInFlightRequest(request); 376 EraseInFlightRequest(request);
345 377
346 // Removing this request may have freed up another to load. 378 // Removing this request may have freed up another to load.
347 LoadAnyStartablePendingRequests(); 379 LoadAnyStartablePendingRequests(
380 has_html_body_
381 ? RequestStartTrigger::COMPLETION_POST_BODY
382 : RequestStartTrigger::COMPLETION_PRE_BODY);
348 } 383 }
349 } 384 }
350 385
351 RequestSet StartAndRemoveAllRequests() { 386 RequestSet StartAndRemoveAllRequests() {
352 // First start any pending requests so that they will be moved into 387 // First start any pending requests so that they will be moved into
353 // in_flight_requests_. This may exceed the limits 388 // in_flight_requests_. This may exceed the limits
354 // kDefaultMaxNumDelayableRequestsPerClient and 389 // kDefaultMaxNumDelayableRequestsPerClient and
355 // kMaxNumDelayableRequestsPerHostPerClient, so this method must not do 390 // kMaxNumDelayableRequestsPerHostPerClient, so this method must not do
356 // anything that depends on those limits before calling 391 // anything that depends on those limits before calling
357 // ClearInFlightRequests() below. 392 // ClearInFlightRequests() below.
358 while (!pending_requests_.IsEmpty()) { 393 while (!pending_requests_.IsEmpty()) {
359 ScheduledResourceRequest* request = 394 ScheduledResourceRequest* request =
360 *pending_requests_.GetNextHighestIterator(); 395 *pending_requests_.GetNextHighestIterator();
361 pending_requests_.Erase(request); 396 pending_requests_.Erase(request);
362 // Starting requests asynchronously ensures no side effects, and avoids 397 // Starting requests asynchronously ensures no side effects, and avoids
363 // starting a bunch of requests that may be about to be deleted. 398 // starting a bunch of requests that may be about to be deleted.
364 StartRequest(request, START_ASYNC); 399 StartRequest(request, START_ASYNC, RequestStartTrigger::CLIENT_KILL);
365 } 400 }
366 RequestSet unowned_requests; 401 RequestSet unowned_requests;
367 for (RequestSet::iterator it = in_flight_requests_.begin(); 402 for (RequestSet::iterator it = in_flight_requests_.begin();
368 it != in_flight_requests_.end(); ++it) { 403 it != in_flight_requests_.end(); ++it) {
369 unowned_requests.insert(*it); 404 unowned_requests.insert(*it);
370 (*it)->set_attributes(kAttributeNone); 405 (*it)->set_attributes(kAttributeNone);
371 } 406 }
372 ClearInFlightRequests(); 407 ClearInFlightRequests();
373 return unowned_requests; 408 return unowned_requests;
374 } 409 }
375 410
376 bool is_loaded() const { return is_loaded_; } 411 bool is_loaded() const { return is_loaded_; }
377 412
378 void OnLoadingStateChanged(bool is_loaded) { 413 void OnLoadingStateChanged(bool is_loaded) {
379 is_loaded_ = is_loaded; 414 is_loaded_ = is_loaded;
380 } 415 }
381 416
382 void OnNavigate() { 417 void OnNavigate() {
383 has_html_body_ = false; 418 has_html_body_ = false;
384 is_loaded_ = false; 419 is_loaded_ = false;
385 } 420 }
386 421
387 void OnWillInsertBody() { 422 void OnWillInsertBody() {
388 has_html_body_ = true; 423 has_html_body_ = true;
389 LoadAnyStartablePendingRequests(); 424 LoadAnyStartablePendingRequests(RequestStartTrigger::BODY_REACHED);
390 } 425 }
391 426
392 void OnReceivedSpdyProxiedHttpResponse() { 427 void OnReceivedSpdyProxiedHttpResponse() {
393 if (!using_spdy_proxy_) { 428 if (!using_spdy_proxy_) {
394 using_spdy_proxy_ = true; 429 using_spdy_proxy_ = true;
395 LoadAnyStartablePendingRequests(); 430 LoadAnyStartablePendingRequests(RequestStartTrigger::SPDY_PROXY_DETECTED);
396 } 431 }
397 } 432 }
398 433
399 void ReprioritizeRequest(ScheduledResourceRequest* request, 434 void ReprioritizeRequest(ScheduledResourceRequest* request,
400 RequestPriorityParams old_priority_params, 435 RequestPriorityParams old_priority_params,
401 RequestPriorityParams new_priority_params) { 436 RequestPriorityParams new_priority_params) {
402 request->url_request()->SetPriority(new_priority_params.priority); 437 request->url_request()->SetPriority(new_priority_params.priority);
403 request->set_request_priority_params(new_priority_params); 438 request->set_request_priority_params(new_priority_params);
404 SetRequestAttributes(request, DetermineRequestAttributes(request)); 439 SetRequestAttributes(request, DetermineRequestAttributes(request));
405 if (!pending_requests_.IsQueued(request)) { 440 if (!pending_requests_.IsQueued(request)) {
406 DCHECK(base::ContainsKey(in_flight_requests_, request)); 441 DCHECK(base::ContainsKey(in_flight_requests_, request));
407 // Request has already started. 442 // Request has already started.
408 return; 443 return;
409 } 444 }
410 445
411 pending_requests_.Erase(request); 446 pending_requests_.Erase(request);
412 pending_requests_.Insert(request); 447 pending_requests_.Insert(request);
413 448
414 if (new_priority_params.priority > old_priority_params.priority) { 449 if (new_priority_params.priority > old_priority_params.priority) {
415 // Check if this request is now able to load at its new priority. 450 // Check if this request is now able to load at its new priority.
416 LoadAnyStartablePendingRequests(); 451 LoadAnyStartablePendingRequests(
452 RequestStartTrigger::REQUEST_REPRIORITIZED);
417 } 453 }
418 } 454 }
419 455
420 private: 456 private:
421 enum ShouldStartReqResult { 457 enum ShouldStartReqResult {
422 DO_NOT_START_REQUEST_AND_STOP_SEARCHING, 458 DO_NOT_START_REQUEST_AND_STOP_SEARCHING,
423 DO_NOT_START_REQUEST_AND_KEEP_SEARCHING, 459 DO_NOT_START_REQUEST_AND_KEEP_SEARCHING,
424 START_REQUEST, 460 START_REQUEST,
425 }; 461 };
426 462
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
552 if (active_request_host.Equals((*it)->host_port_pair())) { 588 if (active_request_host.Equals((*it)->host_port_pair())) {
553 same_host_count++; 589 same_host_count++;
554 if (same_host_count >= kMaxNumDelayableRequestsPerHostPerClient) 590 if (same_host_count >= kMaxNumDelayableRequestsPerHostPerClient)
555 return true; 591 return true;
556 } 592 }
557 } 593 }
558 return false; 594 return false;
559 } 595 }
560 596
561 void StartRequest(ScheduledResourceRequest* request, 597 void StartRequest(ScheduledResourceRequest* request,
562 StartMode start_mode) { 598 StartMode start_mode,
599 RequestStartTrigger trigger) {
600 // Only log on requests that were blocked by the ResourceScheduler.
601 if (start_mode == START_ASYNC) {
602 DCHECK_NE(RequestStartTrigger::NONE, trigger);
603 request->url_request()->net_log().AddEvent(
604 net::NetLogEventType::RESOURCE_SCHEDULER_REQUEST_STARTED,
605 net::NetLog::StringCallback(
606 "trigger", RequestStartTriggerString(trigger)));
607 }
563 InsertInFlightRequest(request); 608 InsertInFlightRequest(request);
564 request->Start(start_mode); 609 request->Start(start_mode);
565 } 610 }
566 611
567 // ShouldStartRequest is the main scheduling algorithm. 612 // ShouldStartRequest is the main scheduling algorithm.
568 // 613 //
569 // Requests are evaluated on five attributes: 614 // Requests are evaluated on five attributes:
570 // 615 //
571 // 1. Non-delayable requests: 616 // 1. Non-delayable requests:
572 // * Synchronous requests. 617 // * Synchronous requests.
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
662 // Block the request if at least one request is in flight and the 707 // Block the request if at least one request is in flight and the
663 // number of in-flight delayable requests has hit the configured 708 // number of in-flight delayable requests has hit the configured
664 // limit. 709 // limit.
665 return DO_NOT_START_REQUEST_AND_STOP_SEARCHING; 710 return DO_NOT_START_REQUEST_AND_STOP_SEARCHING;
666 } 711 }
667 } 712 }
668 713
669 return START_REQUEST; 714 return START_REQUEST;
670 } 715 }
671 716
672 void LoadAnyStartablePendingRequests() { 717 void LoadAnyStartablePendingRequests(RequestStartTrigger trigger) {
673 // We iterate through all the pending requests, starting with the highest 718 // We iterate through all the pending requests, starting with the highest
674 // priority one. For each entry, one of three things can happen: 719 // priority one. For each entry, one of three things can happen:
675 // 1) We start the request, remove it from the list, and keep checking. 720 // 1) We start the request, remove it from the list, and keep checking.
676 // 2) We do NOT start the request, but ShouldStartRequest() signals us that 721 // 2) We do NOT start the request, but ShouldStartRequest() signals us that
677 // there may be room for other requests, so we keep checking and leave 722 // there may be room for other requests, so we keep checking and leave
678 // the previous request still in the list. 723 // the previous request still in the list.
679 // 3) We do not start the request, same as above, but StartRequest() tells 724 // 3) We do not start the request, same as above, but StartRequest() tells
680 // us there's no point in checking any further requests. 725 // us there's no point in checking any further requests.
681 RequestQueue::NetQueue::iterator request_iter = 726 RequestQueue::NetQueue::iterator request_iter =
682 pending_requests_.GetNextHighestIterator(); 727 pending_requests_.GetNextHighestIterator();
683 728
684 while (request_iter != pending_requests_.End()) { 729 while (request_iter != pending_requests_.End()) {
685 ScheduledResourceRequest* request = *request_iter; 730 ScheduledResourceRequest* request = *request_iter;
686 ShouldStartReqResult query_result = ShouldStartRequest(request); 731 ShouldStartReqResult query_result = ShouldStartRequest(request);
687 732
688 if (query_result == START_REQUEST) { 733 if (query_result == START_REQUEST) {
689 pending_requests_.Erase(request); 734 pending_requests_.Erase(request);
690 StartRequest(request, START_ASYNC); 735 StartRequest(request, START_ASYNC, trigger);
691 736
692 // StartRequest can modify the pending list, so we (re)start evaluation 737 // StartRequest can modify the pending list, so we (re)start evaluation
693 // from the currently highest priority request. Avoid copying a singular 738 // from the currently highest priority request. Avoid copying a singular
694 // iterator, which would trigger undefined behavior. 739 // iterator, which would trigger undefined behavior.
695 if (pending_requests_.GetNextHighestIterator() == 740 if (pending_requests_.GetNextHighestIterator() ==
696 pending_requests_.End()) 741 pending_requests_.End())
697 break; 742 break;
698 request_iter = pending_requests_.GetNextHighestIterator(); 743 request_iter = pending_requests_.GetNextHighestIterator();
699 } else if (query_result == DO_NOT_START_REQUEST_AND_KEEP_SEARCHING) { 744 } else if (query_result == DO_NOT_START_REQUEST_AND_KEEP_SEARCHING) {
700 ++request_iter; 745 ++request_iter;
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after
914 client->ReprioritizeRequest(scheduled_resource_request, old_priority_params, 959 client->ReprioritizeRequest(scheduled_resource_request, old_priority_params,
915 new_priority_params); 960 new_priority_params);
916 } 961 }
917 962
918 ResourceScheduler::ClientId ResourceScheduler::MakeClientId( 963 ResourceScheduler::ClientId ResourceScheduler::MakeClientId(
919 int child_id, int route_id) { 964 int child_id, int route_id) {
920 return (static_cast<ResourceScheduler::ClientId>(child_id) << 32) | route_id; 965 return (static_cast<ResourceScheduler::ClientId>(child_id) << 32) | route_id;
921 } 966 }
922 967
923 } // namespace content 968 } // namespace content
OLDNEW
« no previous file with comments | « chrome/browser/resources/net_internals/source_entry.js ('k') | net/log/net_log_event_type_list.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698