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

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

Issue 692723002: Add histograms to gather ResourceScheduler information. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebasing for histograms.xml file. Created 6 years, 1 month 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
« no previous file with comments | « content/browser/loader/resource_scheduler.h ('k') | tools/metrics/histograms/histograms.xml » ('j') | 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 <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/stl_util.h" 11 #include "base/stl_util.h"
12 #include "base/time/time.h"
11 #include "content/common/resource_messages.h" 13 #include "content/common/resource_messages.h"
12 #include "content/browser/loader/resource_message_delegate.h" 14 #include "content/browser/loader/resource_message_delegate.h"
13 #include "content/public/browser/resource_controller.h" 15 #include "content/public/browser/resource_controller.h"
14 #include "content/public/browser/resource_request_info.h" 16 #include "content/public/browser/resource_request_info.h"
15 #include "content/public/browser/resource_throttle.h" 17 #include "content/public/browser/resource_throttle.h"
16 #include "ipc/ipc_message_macros.h" 18 #include "ipc/ipc_message_macros.h"
17 #include "net/base/host_port_pair.h" 19 #include "net/base/host_port_pair.h"
18 #include "net/base/load_flags.h" 20 #include "net/base/load_flags.h"
19 #include "net/base/request_priority.h" 21 #include "net/base/request_priority.h"
20 #include "net/http/http_server_properties.h" 22 #include "net/http/http_server_properties.h"
21 #include "net/url_request/url_request.h" 23 #include "net/url_request/url_request.h"
22 #include "net/url_request/url_request_context.h" 24 #include "net/url_request/url_request_context.h"
23 25
24 namespace content { 26 namespace content {
25 27
28 namespace {
29
30 void PostHistogram(const char* base_name,
31 const char* suffix,
32 base::TimeDelta time) {
33 std::string histogram_name =
34 base::StringPrintf("ResourceScheduler.%s_%s", base_name, suffix);
Ilya Sherman 2014/11/03 23:03:45 Optional nit: Out of curiousity, why are you using
aiolos (Not reviewing) 2014/11/04 00:15:31 It's the form I saw used with the only other histo
35 base::HistogramBase* histogram_counter = base::Histogram::FactoryTimeGet(
36 histogram_name,
37 base::TimeDelta::FromMilliseconds(1),
38 base::TimeDelta::FromMinutes(5),
39 50,
40 base::Histogram::kUmaTargetedHistogramFlag);
41 histogram_counter->AddTime(time);
42 }
43
44 } // namespace
45
26 static const size_t kCoalescedTimerPeriod = 5000; 46 static const size_t kCoalescedTimerPeriod = 5000;
27 static const size_t kMaxNumDelayableRequestsPerClient = 10; 47 static const size_t kMaxNumDelayableRequestsPerClient = 10;
28 static const size_t kMaxNumDelayableRequestsPerHost = 6; 48 static const size_t kMaxNumDelayableRequestsPerHost = 6;
29 static const size_t kMaxNumThrottledRequestsPerClient = 1; 49 static const size_t kMaxNumThrottledRequestsPerClient = 1;
30 50
31 struct ResourceScheduler::RequestPriorityParams { 51 struct ResourceScheduler::RequestPriorityParams {
32 RequestPriorityParams() 52 RequestPriorityParams()
33 : priority(net::DEFAULT_PRIORITY), 53 : priority(net::DEFAULT_PRIORITY),
34 intra_priority(0) { 54 intra_priority(0) {
35 } 55 }
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
116 class ResourceScheduler::ScheduledResourceRequest 136 class ResourceScheduler::ScheduledResourceRequest
117 : public ResourceMessageDelegate, 137 : public ResourceMessageDelegate,
118 public ResourceThrottle { 138 public ResourceThrottle {
119 public: 139 public:
120 ScheduledResourceRequest(const ClientId& client_id, 140 ScheduledResourceRequest(const ClientId& client_id,
121 net::URLRequest* request, 141 net::URLRequest* request,
122 ResourceScheduler* scheduler, 142 ResourceScheduler* scheduler,
123 const RequestPriorityParams& priority) 143 const RequestPriorityParams& priority)
124 : ResourceMessageDelegate(request), 144 : ResourceMessageDelegate(request),
125 client_id_(client_id), 145 client_id_(client_id),
146 client_state_on_creation_(scheduler->GetClientState(client_id_)),
126 request_(request), 147 request_(request),
127 ready_(false), 148 ready_(false),
128 deferred_(false), 149 deferred_(false),
129 classification_(NORMAL_REQUEST), 150 classification_(NORMAL_REQUEST),
130 scheduler_(scheduler), 151 scheduler_(scheduler),
131 priority_(priority), 152 priority_(priority),
132 fifo_ordering_(0) { 153 fifo_ordering_(0) {
133 TRACE_EVENT_ASYNC_BEGIN1("net", "URLRequest", request_, 154 TRACE_EVENT_ASYNC_BEGIN1("net", "URLRequest", request_,
134 "url", request->url().spec()); 155 "url", request->url().spec());
135 } 156 }
136 157
137 ~ScheduledResourceRequest() override { scheduler_->RemoveRequest(this); } 158 ~ScheduledResourceRequest() override { scheduler_->RemoveRequest(this); }
138 159
139 void Start() { 160 void Start() {
140 TRACE_EVENT_ASYNC_STEP_PAST0("net", "URLRequest", request_, "Queued"); 161 TRACE_EVENT_ASYNC_STEP_PAST0("net", "URLRequest", request_, "Queued");
141 ready_ = true; 162 ready_ = true;
142 if (deferred_ && request_->status().is_success()) { 163 if (!request_->status().is_success())
164 return;
165 base::TimeTicks time = base::TimeTicks::Now();
166 ClientState current_state = scheduler_->GetClientState(client_id_);
167 // Note: the client state isn't perfectly accurate since it won't capture
168 // tabs which have switched between active and background multiple times.
169 // Ex: A tab with the following transitions Active -> Background -> Active
170 // will be recorded as Active.
171 const char* client_state = "Other";
172 if (current_state == client_state_on_creation_ && current_state == ACTIVE) {
173 client_state = "Active";
174 } else if (current_state == client_state_on_creation_ &&
175 current_state == BACKGROUND) {
176 client_state = "Background";
177 }
178
179 if (deferred_) {
143 deferred_ = false; 180 deferred_ = false;
144 controller()->Resume(); 181 controller()->Resume();
182 PostHistogram("RequestTimeDeferred", client_state, time - time_deferred_);
183 } else {
184 PostHistogram("RequestTimeDeferred",
Ilya Sherman 2014/11/03 23:03:45 In general, it's nice not to have to repeat histog
aiolos (Not reviewing) 2014/11/04 00:15:31 Done.
185 client_state,
186 base::TimeDelta::FromMicroseconds(0));
145 } 187 }
188 PostHistogram(
189 "RequestTimeThrottled", client_state, time - request_->creation_time());
190 // TODO(aiolos): Remove one of the above sets of histograms after gaining an
191 // understanding of the difference between them and which one is more
192 // interesting.
146 } 193 }
147 194
148 void set_request_priority_params(const RequestPriorityParams& priority) { 195 void set_request_priority_params(const RequestPriorityParams& priority) {
149 priority_ = priority; 196 priority_ = priority;
150 } 197 }
151 const RequestPriorityParams& get_request_priority_params() const { 198 const RequestPriorityParams& get_request_priority_params() const {
152 return priority_; 199 return priority_;
153 } 200 }
154 const ClientId& client_id() const { return client_id_; } 201 const ClientId& client_id() const { return client_id_; }
155 net::URLRequest* url_request() { return request_; } 202 net::URLRequest* url_request() { return request_; }
(...skipping 14 matching lines...) Expand all
170 bool OnMessageReceived(const IPC::Message& message) override { 217 bool OnMessageReceived(const IPC::Message& message) override {
171 bool handled = true; 218 bool handled = true;
172 IPC_BEGIN_MESSAGE_MAP(ScheduledResourceRequest, message) 219 IPC_BEGIN_MESSAGE_MAP(ScheduledResourceRequest, message)
173 IPC_MESSAGE_HANDLER(ResourceHostMsg_DidChangePriority, DidChangePriority) 220 IPC_MESSAGE_HANDLER(ResourceHostMsg_DidChangePriority, DidChangePriority)
174 IPC_MESSAGE_UNHANDLED(handled = false) 221 IPC_MESSAGE_UNHANDLED(handled = false)
175 IPC_END_MESSAGE_MAP() 222 IPC_END_MESSAGE_MAP()
176 return handled; 223 return handled;
177 } 224 }
178 225
179 // ResourceThrottle interface: 226 // ResourceThrottle interface:
180 void WillStartRequest(bool* defer) override { deferred_ = *defer = !ready_; } 227 void WillStartRequest(bool* defer) override {
228 deferred_ = *defer = !ready_;
229 time_deferred_ = base::TimeTicks::Now();
230 }
181 231
182 const char* GetNameForLogging() const override { return "ResourceScheduler"; } 232 const char* GetNameForLogging() const override { return "ResourceScheduler"; }
183 233
184 void DidChangePriority(int request_id, net::RequestPriority new_priority, 234 void DidChangePriority(int request_id, net::RequestPriority new_priority,
185 int intra_priority_value) { 235 int intra_priority_value) {
186 scheduler_->ReprioritizeRequest(this, new_priority, intra_priority_value); 236 scheduler_->ReprioritizeRequest(this, new_priority, intra_priority_value);
187 } 237 }
188 238
189 ClientId client_id_; 239 const ClientId client_id_;
240 const ResourceScheduler::ClientState client_state_on_creation_;
190 net::URLRequest* request_; 241 net::URLRequest* request_;
191 bool ready_; 242 bool ready_;
192 bool deferred_; 243 bool deferred_;
193 RequestClassification classification_; 244 RequestClassification classification_;
194 ResourceScheduler* scheduler_; 245 ResourceScheduler* scheduler_;
195 RequestPriorityParams priority_; 246 RequestPriorityParams priority_;
196 uint32 fifo_ordering_; 247 uint32 fifo_ordering_;
248 base::TimeTicks time_deferred_;
197 249
198 DISALLOW_COPY_AND_ASSIGN(ScheduledResourceRequest); 250 DISALLOW_COPY_AND_ASSIGN(ScheduledResourceRequest);
199 }; 251 };
200 252
201 bool ResourceScheduler::ScheduledResourceSorter::operator()( 253 bool ResourceScheduler::ScheduledResourceSorter::operator()(
202 const ScheduledResourceRequest* a, 254 const ScheduledResourceRequest* a,
203 const ScheduledResourceRequest* b) const { 255 const ScheduledResourceRequest* b) const {
204 // Want the set to be ordered first by decreasing priority, then by 256 // Want the set to be ordered first by decreasing priority, then by
205 // decreasing intra_priority. 257 // decreasing intra_priority.
206 // ie. with (priority, intra_priority) 258 // ie. with (priority, intra_priority)
(...skipping 540 matching lines...) Expand 10 before | Expand all | Expand 10 after
747 DCHECK(client); 799 DCHECK(client);
748 return client->throttle_state(); 800 return client->throttle_state();
749 } 801 }
750 802
751 scoped_ptr<ResourceThrottle> ResourceScheduler::ScheduleRequest( 803 scoped_ptr<ResourceThrottle> ResourceScheduler::ScheduleRequest(
752 int child_id, 804 int child_id,
753 int route_id, 805 int route_id,
754 net::URLRequest* url_request) { 806 net::URLRequest* url_request) {
755 DCHECK(CalledOnValidThread()); 807 DCHECK(CalledOnValidThread());
756 ClientId client_id = MakeClientId(child_id, route_id); 808 ClientId client_id = MakeClientId(child_id, route_id);
757 scoped_ptr<ScheduledResourceRequest> request( 809 scoped_ptr<ScheduledResourceRequest> request(new ScheduledResourceRequest(
758 new ScheduledResourceRequest(client_id, url_request, this, 810 client_id,
759 RequestPriorityParams(url_request->priority(), 0))); 811 url_request,
812 this,
813 RequestPriorityParams(url_request->priority(), 0)));
760 814
761 ClientMap::iterator it = client_map_.find(client_id); 815 ClientMap::iterator it = client_map_.find(client_id);
762 if (it == client_map_.end()) { 816 if (it == client_map_.end()) {
763 // There are several ways this could happen: 817 // There are several ways this could happen:
764 // 1. <a ping> requests don't have a route_id. 818 // 1. <a ping> requests don't have a route_id.
765 // 2. Most unittests don't send the IPCs needed to register Clients. 819 // 2. Most unittests don't send the IPCs needed to register Clients.
766 // 3. The tab is closed while a RequestResource IPC is in flight. 820 // 3. The tab is closed while a RequestResource IPC is in flight.
767 unowned_requests_.insert(request.get()); 821 unowned_requests_.insert(request.get());
768 request->Start(); 822 request->Start();
769 return request.Pass(); 823 return request.Pass();
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
991 void ResourceScheduler::LoadCoalescedRequests() { 1045 void ResourceScheduler::LoadCoalescedRequests() {
992 DCHECK(should_coalesce_); 1046 DCHECK(should_coalesce_);
993 ClientMap::iterator client_it = client_map_.begin(); 1047 ClientMap::iterator client_it = client_map_.begin();
994 while (client_it != client_map_.end()) { 1048 while (client_it != client_map_.end()) {
995 Client* client = client_it->second; 1049 Client* client = client_it->second;
996 client->LoadCoalescedRequests(); 1050 client->LoadCoalescedRequests();
997 ++client_it; 1051 ++client_it;
998 } 1052 }
999 } 1053 }
1000 1054
1055 ResourceScheduler::ClientState ResourceScheduler::GetClientState(
1056 ClientId client_id) const {
1057 ClientMap::const_iterator client_it = client_map_.find(client_id);
1058 if (client_it == client_map_.end())
1059 return UNKNOWN;
1060 return client_it->second->is_active() ? ACTIVE : BACKGROUND;
1061 }
1062
1001 void ResourceScheduler::ReprioritizeRequest(ScheduledResourceRequest* request, 1063 void ResourceScheduler::ReprioritizeRequest(ScheduledResourceRequest* request,
1002 net::RequestPriority new_priority, 1064 net::RequestPriority new_priority,
1003 int new_intra_priority_value) { 1065 int new_intra_priority_value) {
1004 if (request->url_request()->load_flags() & net::LOAD_IGNORE_LIMITS) { 1066 if (request->url_request()->load_flags() & net::LOAD_IGNORE_LIMITS) {
1005 // We should not be re-prioritizing requests with the 1067 // We should not be re-prioritizing requests with the
1006 // IGNORE_LIMITS flag. 1068 // IGNORE_LIMITS flag.
1007 NOTREACHED(); 1069 NOTREACHED();
1008 return; 1070 return;
1009 } 1071 }
1010 RequestPriorityParams new_priority_params(new_priority, 1072 RequestPriorityParams new_priority_params(new_priority,
(...skipping 18 matching lines...) Expand all
1029 client->ReprioritizeRequest( 1091 client->ReprioritizeRequest(
1030 request, old_priority_params, new_priority_params); 1092 request, old_priority_params, new_priority_params);
1031 } 1093 }
1032 1094
1033 ResourceScheduler::ClientId ResourceScheduler::MakeClientId( 1095 ResourceScheduler::ClientId ResourceScheduler::MakeClientId(
1034 int child_id, int route_id) { 1096 int child_id, int route_id) {
1035 return (static_cast<ResourceScheduler::ClientId>(child_id) << 32) | route_id; 1097 return (static_cast<ResourceScheduler::ClientId>(child_id) << 32) | route_id;
1036 } 1098 }
1037 1099
1038 } // namespace content 1100 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/loader/resource_scheduler.h ('k') | tools/metrics/histograms/histograms.xml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698