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

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

Issue 2579933002: Add logging for ResourceScheduler events. (Closed)
Patch Set: Created 4 years 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 "Request completed (pre-body tag)";
71 case RequestStartTrigger::COMPLETION_POST_BODY:
72 return "Request completed (post-body tag)";
73 case RequestStartTrigger::BODY_REACHED:
74 return "Body tag reached";
75 case RequestStartTrigger::CLIENT_KILL:
76 return "Client killed";
77 case RequestStartTrigger::SPDY_PROXY_DETECTED:
78 return "HTTPS proxy detected";
mmenke 2016/12/16 16:46:46 Note that we support non-SPDY HTTPS proxies, too.
Randy Smith (Not in Mondays) 2016/12/20 16:54:17 I think this means you think I should change the s
mmenke 2017/01/03 20:32:29 Yea, I was thinking SPDY proxy detected (Or H2).
Randy Smith (Not in Mondays) 2017/01/03 22:19:29 Arggh, I was typing "HTTPS" and meaning "H2". Got
79 case RequestStartTrigger::REQUEST_REPRIORITIZED:
80 return "Request reprioritized";
mmenke 2016/12/16 16:46:46 Optional nit: I suggest just matching the enum st
Randy Smith (Not in Mondays) 2016/12/20 16:54:17 Done.
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
64 // The maximum number of delayable requests to allow to be in-flight at any 96 // The maximum number of delayable requests to allow to be in-flight at any
65 // point in time while in the layout-blocking phase of loading. 97 // point in time while in the layout-blocking phase of loading.
66 static const size_t kMaxNumDelayableWhileLayoutBlockingPerClient = 1; 98 static const size_t kMaxNumDelayableWhileLayoutBlockingPerClient = 1;
67 99
68 // The priority level above which resources are considered layout-blocking if 100 // The priority level above which resources are considered layout-blocking if
69 // the html_body has not started. 101 // the html_body has not started.
70 static const net::RequestPriority 102 static const net::RequestPriority
71 kLayoutBlockingPriorityThreshold = net::MEDIUM; 103 kLayoutBlockingPriorityThreshold = net::MEDIUM;
72 104
73 // The priority level below which resources are considered to be delayable. 105 // The priority level below which resources are considered to be delayable.
74 static const net::RequestPriority 106 static const net::RequestPriority
75 kDelayablePriorityThreshold = net::MEDIUM; 107 kDelayablePriorityThreshold = net::MEDIUM;
76 108
77 // The number of in-flight layout-blocking requests above which all delayable 109 // The number of in-flight layout-blocking requests above which all delayable
78 // requests should be blocked. 110 // requests should be blocked.
79 static const size_t kInFlightNonDelayableRequestCountPerClientThreshold = 1; 111 static const size_t kInFlightNonDelayableRequestCountPerClientThreshold = 1;
80 112
113 // Sets an integer on construction and resets it to its original
114 // value on destruction. Value pointed to must be guaranteed by the caller
115 // to remain alive for the lifetime of this class.
116 template <class T>
117 class ScopedSetter {
118 public:
119 ScopedSetter(T* target, T value) {
120 target_ = target;
121 original_value_ = *target;
122 *target = value;
123 }
124
125 ~ScopedSetter() { *target_ = original_value_; }
126
127 private:
128 DISALLOW_COPY_AND_ASSIGN(ScopedSetter);
129
130 T* target_;
131 T original_value_;
132 };
133
134 using ScopedTrigger = ScopedSetter<RequestStartTrigger>;
mmenke 2016/12/16 16:46:46 This seems like over-engineering to me, and I'm no
Randy Smith (Not in Mondays) 2016/12/20 16:54:17 I dunno if this helps, but I finally tracked down
mmenke 2017/01/03 20:32:29 I don't think functions should know or care exactl
Charlie Harrison 2017/01/03 21:22:49 mmenke, I'm guessing you would prefer threading th
mmenke 2017/01/03 21:24:44 Yes, that's what I'd do (Though, like I said, cert
Randy Smith (Not in Mondays) 2017/01/03 22:19:29 I hear and sympathize with you both, but I think t
135
81 struct ResourceScheduler::RequestPriorityParams { 136 struct ResourceScheduler::RequestPriorityParams {
82 RequestPriorityParams() 137 RequestPriorityParams()
83 : priority(net::DEFAULT_PRIORITY), 138 : priority(net::DEFAULT_PRIORITY),
84 intra_priority(0) { 139 intra_priority(0) {
85 } 140 }
86 141
87 RequestPriorityParams(net::RequestPriority priority, int intra_priority) 142 RequestPriorityParams(net::RequestPriority priority, int intra_priority)
88 : priority(priority), 143 : priority(priority),
89 intra_priority(intra_priority) { 144 intra_priority(intra_priority) {
90 } 145 }
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after
314 369
315 // Each client represents a tab. 370 // Each client represents a tab.
316 class ResourceScheduler::Client { 371 class ResourceScheduler::Client {
317 public: 372 public:
318 explicit Client(bool priority_requests_delayable) 373 explicit Client(bool priority_requests_delayable)
319 : is_loaded_(false), 374 : is_loaded_(false),
320 has_html_body_(false), 375 has_html_body_(false),
321 using_spdy_proxy_(false), 376 using_spdy_proxy_(false),
322 in_flight_delayable_count_(0), 377 in_flight_delayable_count_(0),
323 total_layout_blocking_count_(0), 378 total_layout_blocking_count_(0),
324 priority_requests_delayable_(priority_requests_delayable) {} 379 priority_requests_delayable_(priority_requests_delayable),
380 request_start_trigger_(RequestStartTrigger::NONE) {}
325 381
326 ~Client() {} 382 ~Client() {}
327 383
328 void ScheduleRequest(net::URLRequest* url_request, 384 void ScheduleRequest(net::URLRequest* url_request,
329 ScheduledResourceRequest* request) { 385 ScheduledResourceRequest* request) {
330 SetRequestAttributes(request, DetermineRequestAttributes(request)); 386 SetRequestAttributes(request, DetermineRequestAttributes(request));
331 if (ShouldStartRequest(request) == START_REQUEST) { 387 if (ShouldStartRequest(request) == START_REQUEST) {
332 // New requests can be started synchronously without issue. 388 // New requests can be started synchronously without issue.
333 StartRequest(request, START_SYNC); 389 StartRequest(request, START_SYNC);
334 } else { 390 } else {
391 request->url_request()->net_log().AddEvent(
392 net::NetLogEventType::RESOURCE_SCHEDULER_REQUEST_BLOCKED);
335 pending_requests_.Insert(request); 393 pending_requests_.Insert(request);
336 } 394 }
337 } 395 }
338 396
339 void RemoveRequest(ScheduledResourceRequest* request) { 397 void RemoveRequest(ScheduledResourceRequest* request) {
398 ScopedTrigger scoped_trigger(
399 &request_start_trigger_,
400 has_html_body_ ? RequestStartTrigger::COMPLETION_POST_BODY
401 : RequestStartTrigger::COMPLETION_PRE_BODY);
402
340 if (pending_requests_.IsQueued(request)) { 403 if (pending_requests_.IsQueued(request)) {
341 pending_requests_.Erase(request); 404 pending_requests_.Erase(request);
342 DCHECK(!base::ContainsKey(in_flight_requests_, request)); 405 DCHECK(!base::ContainsKey(in_flight_requests_, request));
343 } else { 406 } else {
344 EraseInFlightRequest(request); 407 EraseInFlightRequest(request);
345 408
346 // Removing this request may have freed up another to load. 409 // Removing this request may have freed up another to load.
347 LoadAnyStartablePendingRequests(); 410 LoadAnyStartablePendingRequests();
348 } 411 }
349 } 412 }
350 413
351 RequestSet StartAndRemoveAllRequests() { 414 RequestSet StartAndRemoveAllRequests() {
415 ScopedTrigger scoped_trigger(&request_start_trigger_,
416 RequestStartTrigger::CLIENT_KILL);
417
352 // First start any pending requests so that they will be moved into 418 // First start any pending requests so that they will be moved into
353 // in_flight_requests_. This may exceed the limits 419 // in_flight_requests_. This may exceed the limits
354 // kDefaultMaxNumDelayableRequestsPerClient and 420 // kDefaultMaxNumDelayableRequestsPerClient and
355 // kMaxNumDelayableRequestsPerHostPerClient, so this method must not do 421 // kMaxNumDelayableRequestsPerHostPerClient, so this method must not do
356 // anything that depends on those limits before calling 422 // anything that depends on those limits before calling
357 // ClearInFlightRequests() below. 423 // ClearInFlightRequests() below.
358 while (!pending_requests_.IsEmpty()) { 424 while (!pending_requests_.IsEmpty()) {
359 ScheduledResourceRequest* request = 425 ScheduledResourceRequest* request =
360 *pending_requests_.GetNextHighestIterator(); 426 *pending_requests_.GetNextHighestIterator();
361 pending_requests_.Erase(request); 427 pending_requests_.Erase(request);
(...skipping 16 matching lines...) Expand all
378 void OnLoadingStateChanged(bool is_loaded) { 444 void OnLoadingStateChanged(bool is_loaded) {
379 is_loaded_ = is_loaded; 445 is_loaded_ = is_loaded;
380 } 446 }
381 447
382 void OnNavigate() { 448 void OnNavigate() {
383 has_html_body_ = false; 449 has_html_body_ = false;
384 is_loaded_ = false; 450 is_loaded_ = false;
385 } 451 }
386 452
387 void OnWillInsertBody() { 453 void OnWillInsertBody() {
454 ScopedTrigger scoped_trigger(&request_start_trigger_,
455 RequestStartTrigger::BODY_REACHED);
456
388 has_html_body_ = true; 457 has_html_body_ = true;
389 LoadAnyStartablePendingRequests(); 458 LoadAnyStartablePendingRequests();
390 } 459 }
391 460
392 void OnReceivedSpdyProxiedHttpResponse() { 461 void OnReceivedSpdyProxiedHttpResponse() {
462 ScopedTrigger scoped_trigger(&request_start_trigger_,
463 RequestStartTrigger::SPDY_PROXY_DETECTED);
464
393 if (!using_spdy_proxy_) { 465 if (!using_spdy_proxy_) {
394 using_spdy_proxy_ = true; 466 using_spdy_proxy_ = true;
395 LoadAnyStartablePendingRequests(); 467 LoadAnyStartablePendingRequests();
396 } 468 }
397 } 469 }
398 470
399 void ReprioritizeRequest(ScheduledResourceRequest* request, 471 void ReprioritizeRequest(ScheduledResourceRequest* request,
400 RequestPriorityParams old_priority_params, 472 RequestPriorityParams old_priority_params,
401 RequestPriorityParams new_priority_params) { 473 RequestPriorityParams new_priority_params) {
474 ScopedTrigger scoped_trigger(&request_start_trigger_,
475 RequestStartTrigger::REQUEST_REPRIORITIZED);
476
402 request->url_request()->SetPriority(new_priority_params.priority); 477 request->url_request()->SetPriority(new_priority_params.priority);
403 request->set_request_priority_params(new_priority_params); 478 request->set_request_priority_params(new_priority_params);
404 SetRequestAttributes(request, DetermineRequestAttributes(request)); 479 SetRequestAttributes(request, DetermineRequestAttributes(request));
405 if (!pending_requests_.IsQueued(request)) { 480 if (!pending_requests_.IsQueued(request)) {
406 DCHECK(base::ContainsKey(in_flight_requests_, request)); 481 DCHECK(base::ContainsKey(in_flight_requests_, request));
407 // Request has already started. 482 // Request has already started.
408 return; 483 return;
409 } 484 }
410 485
411 pending_requests_.Erase(request); 486 pending_requests_.Erase(request);
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
553 same_host_count++; 628 same_host_count++;
554 if (same_host_count >= kMaxNumDelayableRequestsPerHostPerClient) 629 if (same_host_count >= kMaxNumDelayableRequestsPerHostPerClient)
555 return true; 630 return true;
556 } 631 }
557 } 632 }
558 return false; 633 return false;
559 } 634 }
560 635
561 void StartRequest(ScheduledResourceRequest* request, 636 void StartRequest(ScheduledResourceRequest* request,
562 StartMode start_mode) { 637 StartMode start_mode) {
638 // Only log on requests that were blocked by the ResourceScheduler.
639 if (start_mode == START_ASYNC) {
640 request->url_request()->net_log().AddEvent(
641 net::NetLogEventType::RESOURCE_SCHEDULER_REQUEST_STARTED,
642 net::NetLog::StringCallback(
643 "trigger", RequestStartTriggerString(request_start_trigger_)));
644 }
563 InsertInFlightRequest(request); 645 InsertInFlightRequest(request);
564 request->Start(start_mode); 646 request->Start(start_mode);
565 } 647 }
566 648
567 // ShouldStartRequest is the main scheduling algorithm. 649 // ShouldStartRequest is the main scheduling algorithm.
568 // 650 //
569 // Requests are evaluated on five attributes: 651 // Requests are evaluated on five attributes:
570 // 652 //
571 // 1. Non-delayable requests: 653 // 1. Non-delayable requests:
572 // * Synchronous requests. 654 // * Synchronous requests.
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
714 RequestQueue pending_requests_; 796 RequestQueue pending_requests_;
715 RequestSet in_flight_requests_; 797 RequestSet in_flight_requests_;
716 // The number of delayable in-flight requests. 798 // The number of delayable in-flight requests.
717 size_t in_flight_delayable_count_; 799 size_t in_flight_delayable_count_;
718 // The number of layout-blocking in-flight requests. 800 // The number of layout-blocking in-flight requests.
719 size_t total_layout_blocking_count_; 801 size_t total_layout_blocking_count_;
720 802
721 // True if requests to servers that support priorities (e.g., H2/QUIC) can 803 // True if requests to servers that support priorities (e.g., H2/QUIC) can
722 // be delayed. 804 // be delayed.
723 bool priority_requests_delayable_; 805 bool priority_requests_delayable_;
806
807 // Current start trigger.
808 RequestStartTrigger request_start_trigger_;
724 }; 809 };
725 810
726 ResourceScheduler::ResourceScheduler() 811 ResourceScheduler::ResourceScheduler()
727 : priority_requests_delayable_( 812 : priority_requests_delayable_(
728 base::FeatureList::IsEnabled(kPrioritySupportedRequestsDelayable)) {} 813 base::FeatureList::IsEnabled(kPrioritySupportedRequestsDelayable)) {}
729 814
730 ResourceScheduler::~ResourceScheduler() { 815 ResourceScheduler::~ResourceScheduler() {
731 DCHECK(unowned_requests_.empty()); 816 DCHECK(unowned_requests_.empty());
732 DCHECK(client_map_.empty()); 817 DCHECK(client_map_.empty());
733 } 818 }
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
914 client->ReprioritizeRequest(scheduled_resource_request, old_priority_params, 999 client->ReprioritizeRequest(scheduled_resource_request, old_priority_params,
915 new_priority_params); 1000 new_priority_params);
916 } 1001 }
917 1002
918 ResourceScheduler::ClientId ResourceScheduler::MakeClientId( 1003 ResourceScheduler::ClientId ResourceScheduler::MakeClientId(
919 int child_id, int route_id) { 1004 int child_id, int route_id) {
920 return (static_cast<ResourceScheduler::ClientId>(child_id) << 32) | route_id; 1005 return (static_cast<ResourceScheduler::ClientId>(child_id) << 32) | route_id;
921 } 1006 }
922 1007
923 } // namespace content 1008 } // 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