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

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

Issue 782903002: Breakdown ClientLoadedTime histograms into buckets based on number of clients. Fix RequestTimeThrot… (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 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 <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/time/time.h" 12 #include "base/time/time.h"
13 #include "content/common/resource_messages.h" 13 #include "content/common/resource_messages.h"
14 #include "content/browser/loader/resource_message_delegate.h" 14 #include "content/browser/loader/resource_message_delegate.h"
15 #include "content/public/browser/resource_controller.h" 15 #include "content/public/browser/resource_controller.h"
16 #include "content/public/browser/resource_request_info.h" 16 #include "content/public/browser/resource_request_info.h"
17 #include "content/public/browser/resource_throttle.h" 17 #include "content/public/browser/resource_throttle.h"
18 #include "ipc/ipc_message_macros.h" 18 #include "ipc/ipc_message_macros.h"
19 #include "net/base/host_port_pair.h" 19 #include "net/base/host_port_pair.h"
20 #include "net/base/load_flags.h" 20 #include "net/base/load_flags.h"
21 #include "net/base/request_priority.h" 21 #include "net/base/request_priority.h"
22 #include "net/http/http_server_properties.h" 22 #include "net/http/http_server_properties.h"
23 #include "net/url_request/url_request.h" 23 #include "net/url_request/url_request.h"
24 #include "net/url_request/url_request_context.h" 24 #include "net/url_request/url_request_context.h"
25 25
26 namespace content { 26 namespace content {
27 27
28 namespace { 28 namespace {
29 29
30 void PostHistogram(const char* base_name, 30 void PostHistogram(std::string base_name,
31 const char* suffix, 31 std::string suffix,
Ilya Sherman 2014/12/09 02:59:36 nit: Why not const-ref?
aiolos (Not reviewing) 2015/01/05 23:37:59 Done. I had changed it to std::string to simplify
32 base::TimeDelta time) { 32 base::TimeDelta time) {
33 std::string histogram_name = 33 std::string histogram_name = "ResourceScheduler." + base_name + '.' + suffix;
34 base::StringPrintf("ResourceScheduler.%s.%s", base_name, suffix);
35 base::HistogramBase* histogram_counter = base::Histogram::FactoryTimeGet( 34 base::HistogramBase* histogram_counter = base::Histogram::FactoryTimeGet(
36 histogram_name, 35 histogram_name,
37 base::TimeDelta::FromMilliseconds(1), 36 base::TimeDelta::FromMilliseconds(1),
38 base::TimeDelta::FromMinutes(5), 37 base::TimeDelta::FromMinutes(5),
39 50, 38 50,
40 base::Histogram::kUmaTargetedHistogramFlag); 39 base::Histogram::kUmaTargetedHistogramFlag);
41 histogram_counter->AddTime(time); 40 histogram_counter->AddTime(time);
42 } 41 }
43 42
44 } // namespace 43 } // namespace
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
161 TRACE_EVENT_ASYNC_STEP_PAST0("net", "URLRequest", request_, "Queued"); 160 TRACE_EVENT_ASYNC_STEP_PAST0("net", "URLRequest", request_, "Queued");
162 ready_ = true; 161 ready_ = true;
163 if (!request_->status().is_success()) 162 if (!request_->status().is_success())
164 return; 163 return;
165 base::TimeTicks time = base::TimeTicks::Now(); 164 base::TimeTicks time = base::TimeTicks::Now();
166 ClientState current_state = scheduler_->GetClientState(client_id_); 165 ClientState current_state = scheduler_->GetClientState(client_id_);
167 // Note: the client state isn't perfectly accurate since it won't capture 166 // Note: the client state isn't perfectly accurate since it won't capture
168 // tabs which have switched between active and background multiple times. 167 // tabs which have switched between active and background multiple times.
169 // Ex: A tab with the following transitions Active -> Background -> Active 168 // Ex: A tab with the following transitions Active -> Background -> Active
170 // will be recorded as Active. 169 // will be recorded as Active.
171 const char* client_state = "Other"; 170 std::string client_state = "Other";
172 if (current_state == client_state_on_creation_ && current_state == ACTIVE) { 171 if (current_state == client_state_on_creation_ && current_state == ACTIVE) {
173 client_state = "Active"; 172 client_state = "Active";
174 } else if (current_state == client_state_on_creation_ && 173 } else if (current_state == client_state_on_creation_ &&
175 current_state == BACKGROUND) { 174 current_state == BACKGROUND) {
176 client_state = "Background"; 175 client_state = "Background";
177 } 176 }
178 177
179 base::TimeDelta time_was_deferred = base::TimeDelta::FromMicroseconds(0); 178 base::TimeDelta time_was_deferred = base::TimeDelta::FromMicroseconds(0);
180 if (deferred_) { 179 if (deferred_) {
181 deferred_ = false; 180 deferred_ = false;
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after
361 return; 360 return;
362 } 361 }
363 is_loaded_ = is_loaded; 362 is_loaded_ = is_loaded;
364 UpdateThrottleState(); 363 UpdateThrottleState();
365 if (!is_loaded_) { 364 if (!is_loaded_) {
366 load_started_time_ = base::TimeTicks::Now(); 365 load_started_time_ = base::TimeTicks::Now();
367 last_active_switch_time_ = base::TimeTicks(); 366 last_active_switch_time_ = base::TimeTicks();
368 return; 367 return;
369 } 368 }
370 base::TimeTicks cur_time = base::TimeTicks::Now(); 369 base::TimeTicks cur_time = base::TimeTicks::Now();
371 const char* client_catagory = "Other"; 370 std::string num_clients = scheduler_->GetNumClientsString();
mmenke 2014/12/09 15:53:28 Per suggestion below, can make this a const char*
aiolos (Not reviewing) 2015/01/05 23:37:59 Done.
371 std::string client_catagory = "Other";
372 if (last_active_switch_time_.is_null()) { 372 if (last_active_switch_time_.is_null()) {
373 client_catagory = is_active() ? "Active" : "Background"; 373 client_catagory = is_active() ? "Active" : "Background";
374 } else if (is_active()) { 374 } else if (is_active()) {
375 PostHistogram("ClientLoadedTime", "Other.SwitchedToActive", 375 PostHistogram(
376 "ClientLoadedTime", "Other.SwitchedToActive",
377 cur_time - last_active_switch_time_);
mmenke 2014/12/09 15:53:28 Suggest putting "cur_time - last_active_switch_tim
aiolos (Not reviewing) 2015/01/05 23:37:58 Done.
378 PostHistogram("ClientLoadedTime", "Other.SwitchedToActive." + num_clients,
376 cur_time - last_active_switch_time_); 379 cur_time - last_active_switch_time_);
377 } 380 }
378 PostHistogram("ClientLoadedTime", client_catagory, 381 PostHistogram("ClientLoadedTime", client_catagory,
379 cur_time - load_started_time_); 382 cur_time - load_started_time_);
383 PostHistogram("ClientLoadedTime", client_catagory + '.' + num_clients,
384 cur_time - load_started_time_);
380 // TODO(aiolos): The above histograms will not take main resource load time 385 // TODO(aiolos): The above histograms will not take main resource load time
381 // into account with PlzNavigate into account. The ResourceScheduler also 386 // into account with PlzNavigate into account. The ResourceScheduler also
382 // will load the main resources without a clients with the current logic. 387 // will load the main resources without a clients with the current logic.
383 // Find a way to fix both of these issues. 388 // Find a way to fix both of these issues.
384 } 389 }
385 390
386 void SetPaused() { 391 void SetPaused() {
387 is_paused_ = true; 392 is_paused_ = true;
388 UpdateThrottleState(); 393 UpdateThrottleState();
389 } 394 }
(...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after
783 // The number of delayable in-flight requests. 788 // The number of delayable in-flight requests.
784 size_t in_flight_delayable_count_; 789 size_t in_flight_delayable_count_;
785 // The number of layout-blocking in-flight requests. 790 // The number of layout-blocking in-flight requests.
786 size_t total_layout_blocking_count_; 791 size_t total_layout_blocking_count_;
787 ResourceScheduler::ClientThrottleState throttle_state_; 792 ResourceScheduler::ClientThrottleState throttle_state_;
788 }; 793 };
789 794
790 ResourceScheduler::ResourceScheduler() 795 ResourceScheduler::ResourceScheduler()
791 : should_coalesce_(false), 796 : should_coalesce_(false),
792 should_throttle_(false), 797 should_throttle_(false),
798 num_clients_(0),
793 active_clients_loading_(0), 799 active_clients_loading_(0),
794 coalesced_clients_(0), 800 coalesced_clients_(0),
795 coalescing_timer_(new base::Timer(true /* retain_user_task */, 801 coalescing_timer_(new base::Timer(true /* retain_user_task */,
796 true /* is_repeating */)) { 802 true /* is_repeating */)) {
797 std::string throttling_trial_group = 803 std::string throttling_trial_group =
798 base::FieldTrialList::FindFullName("RequestThrottlingAndCoalescing"); 804 base::FieldTrialList::FindFullName("RequestThrottlingAndCoalescing");
799 if (throttling_trial_group == "Throttle") { 805 if (throttling_trial_group == "Throttle") {
800 should_throttle_ = true; 806 should_throttle_ = true;
801 } else if (throttling_trial_group == "Coalesce") { 807 } else if (throttling_trial_group == "Coalesce") {
802 should_coalesce_ = true; 808 should_coalesce_ = true;
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
871 int route_id, 877 int route_id,
872 bool is_visible, 878 bool is_visible,
873 bool is_audible) { 879 bool is_audible) {
874 DCHECK(CalledOnValidThread()); 880 DCHECK(CalledOnValidThread());
875 ClientId client_id = MakeClientId(child_id, route_id); 881 ClientId client_id = MakeClientId(child_id, route_id);
876 DCHECK(!ContainsKey(client_map_, client_id)); 882 DCHECK(!ContainsKey(client_map_, client_id));
877 883
878 Client* client = new Client(this, is_visible, is_audible); 884 Client* client = new Client(this, is_visible, is_audible);
879 client_map_[client_id] = client; 885 client_map_[client_id] = client;
880 886
881 // TODO(aiolos): set Client visibility/audibility when signals are added
882 // this will UNTHROTTLE Clients as needed
883 client->UpdateThrottleState(); 887 client->UpdateThrottleState();
888 ++num_clients_;
884 } 889 }
885 890
886 void ResourceScheduler::OnClientDeleted(int child_id, int route_id) { 891 void ResourceScheduler::OnClientDeleted(int child_id, int route_id) {
887 DCHECK(CalledOnValidThread()); 892 DCHECK(CalledOnValidThread());
888 ClientId client_id = MakeClientId(child_id, route_id); 893 ClientId client_id = MakeClientId(child_id, route_id);
889 DCHECK(ContainsKey(client_map_, client_id)); 894 DCHECK(ContainsKey(client_map_, client_id));
890 ClientMap::iterator it = client_map_.find(client_id); 895 ClientMap::iterator it = client_map_.find(client_id);
891 if (it == client_map_.end()) 896 if (it == client_map_.end())
892 return; 897 return;
893 898
894 Client* client = it->second; 899 Client* client = it->second;
895 // FYI, ResourceDispatcherHost cancels all of the requests after this function 900 // FYI, ResourceDispatcherHost cancels all of the requests after this function
896 // is called. It should end up canceling all of the requests except for a 901 // is called. It should end up canceling all of the requests except for a
897 // cross-renderer navigation. 902 // cross-renderer navigation.
898 RequestSet client_unowned_requests = client->RemoveAllRequests(); 903 RequestSet client_unowned_requests = client->RemoveAllRequests();
899 for (RequestSet::iterator it = client_unowned_requests.begin(); 904 for (RequestSet::iterator it = client_unowned_requests.begin();
900 it != client_unowned_requests.end(); ++it) { 905 it != client_unowned_requests.end(); ++it) {
901 unowned_requests_.insert(*it); 906 unowned_requests_.insert(*it);
902 } 907 }
903 908
904 delete client; 909 delete client;
905 client_map_.erase(it); 910 client_map_.erase(it);
911 --num_clients_;
906 } 912 }
907 913
908 void ResourceScheduler::OnLoadingStateChanged(int child_id, 914 void ResourceScheduler::OnLoadingStateChanged(int child_id,
909 int route_id, 915 int route_id,
910 bool is_loaded) { 916 bool is_loaded) {
911 Client* client = GetClient(child_id, route_id); 917 Client* client = GetClient(child_id, route_id);
912 DCHECK(client); 918 DCHECK(client);
913 client->OnLoadingStateChanged(is_loaded); 919 client->OnLoadingStateChanged(is_loaded);
914 } 920 }
915 921
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
982 ResourceScheduler::Client* ResourceScheduler::GetClient(int child_id, 988 ResourceScheduler::Client* ResourceScheduler::GetClient(int child_id,
983 int route_id) { 989 int route_id) {
984 ClientId client_id = MakeClientId(child_id, route_id); 990 ClientId client_id = MakeClientId(child_id, route_id);
985 ClientMap::iterator client_it = client_map_.find(client_id); 991 ClientMap::iterator client_it = client_map_.find(client_id);
986 if (client_it == client_map_.end()) { 992 if (client_it == client_map_.end()) {
987 return NULL; 993 return NULL;
988 } 994 }
989 return client_it->second; 995 return client_it->second;
990 } 996 }
991 997
998 std::string ResourceScheduler::GetNumClientsString() {
mmenke 2014/12/09 15:53:28 Can't we return a const char*?
mmenke 2014/12/09 15:53:28 +const. Or better, remove it from ResourceSchedul
aiolos (Not reviewing) 2015/01/05 23:37:59 Done.
aiolos (Not reviewing) 2015/01/05 23:37:59 Done.
999 if (num_clients_ == 1)
mmenke 2014/12/09 15:53:28 I'd recommend just using client_map_.size() instea
aiolos (Not reviewing) 2015/01/05 23:37:59 Done.
1000 return "1Client";
1001 else if (num_clients_ <= 5)
1002 return "Max5Clients";
1003 else if (num_clients_ <= 15)
1004 return "Max15Clients";
1005 else if (num_clients_ <= 30)
1006 return "Max30Clients";
1007 return "Over30Clients";
1008 }
1009
992 void ResourceScheduler::DecrementActiveClientsLoading() { 1010 void ResourceScheduler::DecrementActiveClientsLoading() {
993 DCHECK_NE(0u, active_clients_loading_); 1011 DCHECK_NE(0u, active_clients_loading_);
994 --active_clients_loading_; 1012 --active_clients_loading_;
995 DCHECK_EQ(active_clients_loading_, CountActiveClientsLoading()); 1013 DCHECK_EQ(active_clients_loading_, CountActiveClientsLoading());
996 if (active_clients_loading_ == 0) { 1014 if (active_clients_loading_ == 0) {
997 OnLoadingActiveClientsStateChangedForAllClients(); 1015 OnLoadingActiveClientsStateChangedForAllClients();
998 } 1016 }
999 } 1017 }
1000 1018
1001 void ResourceScheduler::IncrementActiveClientsLoading() { 1019 void ResourceScheduler::IncrementActiveClientsLoading() {
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
1114 client->ReprioritizeRequest( 1132 client->ReprioritizeRequest(
1115 request, old_priority_params, new_priority_params); 1133 request, old_priority_params, new_priority_params);
1116 } 1134 }
1117 1135
1118 ResourceScheduler::ClientId ResourceScheduler::MakeClientId( 1136 ResourceScheduler::ClientId ResourceScheduler::MakeClientId(
1119 int child_id, int route_id) { 1137 int child_id, int route_id) {
1120 return (static_cast<ResourceScheduler::ClientId>(child_id) << 32) | route_id; 1138 return (static_cast<ResourceScheduler::ClientId>(child_id) << 32) | route_id;
1121 } 1139 }
1122 1140
1123 } // namespace content 1141 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698