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

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

Issue 1285863003: ResourceScheduler: remove dependency on ResourceRequestInfo and request_id (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@lkgr
Patch Set: Rename resource_throttle variables back to throttle. Created 5 years, 4 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 <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/strings/string_number_conversions.h" 12 #include "base/strings/string_number_conversions.h"
13 #include "base/strings/string_piece.h" 13 #include "base/strings/string_piece.h"
14 #include "base/supports_user_data.h"
14 #include "base/time/time.h" 15 #include "base/time/time.h"
15 #include "content/common/resource_messages.h" 16 #include "content/common/resource_messages.h"
16 #include "content/browser/loader/resource_message_delegate.h"
17 #include "content/public/browser/resource_controller.h" 17 #include "content/public/browser/resource_controller.h"
18 #include "content/public/browser/resource_request_info.h" 18 #include "content/public/browser/resource_request_info.h"
19 #include "content/public/browser/resource_throttle.h" 19 #include "content/public/browser/resource_throttle.h"
20 #include "ipc/ipc_message_macros.h"
21 #include "net/base/host_port_pair.h" 20 #include "net/base/host_port_pair.h"
22 #include "net/base/load_flags.h" 21 #include "net/base/load_flags.h"
23 #include "net/base/request_priority.h" 22 #include "net/base/request_priority.h"
24 #include "net/http/http_server_properties.h" 23 #include "net/http/http_server_properties.h"
25 #include "net/url_request/url_request.h" 24 #include "net/url_request/url_request.h"
26 #include "net/url_request/url_request_context.h" 25 #include "net/url_request/url_request_context.h"
27 26
28 namespace content { 27 namespace content {
29 28
30 namespace { 29 namespace {
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
156 // Used to create an ordering ID for scheduled resources so that resources 155 // Used to create an ordering ID for scheduled resources so that resources
157 // with same priority/intra_priority stay in fifo order. 156 // with same priority/intra_priority stay in fifo order.
158 uint32 fifo_ordering_ids_; 157 uint32 fifo_ordering_ids_;
159 158
160 NetQueue queue_; 159 NetQueue queue_;
161 PointerMap pointers_; 160 PointerMap pointers_;
162 }; 161 };
163 162
164 // This is the handle we return to the ResourceDispatcherHostImpl so it can 163 // This is the handle we return to the ResourceDispatcherHostImpl so it can
165 // interact with the request. 164 // interact with the request.
166 class ResourceScheduler::ScheduledResourceRequest 165 class ResourceScheduler::ScheduledResourceRequest : public ResourceThrottle {
167 : public ResourceMessageDelegate,
168 public ResourceThrottle {
169 public: 166 public:
170 ScheduledResourceRequest(const ClientId& client_id, 167 ScheduledResourceRequest(const ClientId& client_id,
171 net::URLRequest* request, 168 net::URLRequest* request,
172 ResourceScheduler* scheduler, 169 ResourceScheduler* scheduler,
173 const RequestPriorityParams& priority) 170 const RequestPriorityParams& priority,
174 : ResourceMessageDelegate(request), 171 bool is_async)
175 client_id_(client_id), 172 : client_id_(client_id),
176 client_state_on_creation_(scheduler->GetClientState(client_id_)), 173 client_state_on_creation_(scheduler->GetClientState(client_id_)),
177 request_(request), 174 request_(request),
178 ready_(false), 175 ready_(false),
179 deferred_(false), 176 deferred_(false),
177 is_async_(is_async),
180 classification_(NORMAL_REQUEST), 178 classification_(NORMAL_REQUEST),
181 scheduler_(scheduler), 179 scheduler_(scheduler),
182 priority_(priority), 180 priority_(priority),
183 fifo_ordering_(0) { 181 fifo_ordering_(0) {
182 request_->SetUserData(kUserDataKey, new UnownedPointer(this));
mmenke 2015/08/14 17:24:25 Maybe DCHECK that it doesn't have one already set?
Adam Rice 2015/08/14 17:30:03 Done.
184 } 183 }
185 184
186 ~ScheduledResourceRequest() override { scheduler_->RemoveRequest(this); } 185 ~ScheduledResourceRequest() override {
186 request_->RemoveUserData(kUserDataKey);
187 scheduler_->RemoveRequest(this);
188 }
189
190 static ScheduledResourceRequest* ForRequest(net::URLRequest* request) {
191 return static_cast<UnownedPointer*>(request->GetUserData(kUserDataKey))
192 ->get();
193 }
187 194
188 void Start() { 195 void Start() {
189 ready_ = true; 196 ready_ = true;
190 if (!request_->status().is_success()) 197 if (!request_->status().is_success())
191 return; 198 return;
192 base::TimeTicks time = base::TimeTicks::Now(); 199 base::TimeTicks time = base::TimeTicks::Now();
193 ClientState current_state = scheduler_->GetClientState(client_id_); 200 ClientState current_state = scheduler_->GetClientState(client_id_);
194 // Note: the client state isn't perfectly accurate since it won't capture 201 // Note: the client state isn't perfectly accurate since it won't capture
195 // tabs which have switched between active and background multiple times. 202 // tabs which have switched between active and background multiple times.
196 // Ex: A tab with the following transitions Active -> Background -> Active 203 // Ex: A tab with the following transitions Active -> Background -> Active
(...skipping 22 matching lines...) Expand all
219 226
220 void set_request_priority_params(const RequestPriorityParams& priority) { 227 void set_request_priority_params(const RequestPriorityParams& priority) {
221 priority_ = priority; 228 priority_ = priority;
222 } 229 }
223 const RequestPriorityParams& get_request_priority_params() const { 230 const RequestPriorityParams& get_request_priority_params() const {
224 return priority_; 231 return priority_;
225 } 232 }
226 const ClientId& client_id() const { return client_id_; } 233 const ClientId& client_id() const { return client_id_; }
227 net::URLRequest* url_request() { return request_; } 234 net::URLRequest* url_request() { return request_; }
228 const net::URLRequest* url_request() const { return request_; } 235 const net::URLRequest* url_request() const { return request_; }
236 bool is_async() const { return is_async_; }
229 uint32 fifo_ordering() const { return fifo_ordering_; } 237 uint32 fifo_ordering() const { return fifo_ordering_; }
230 void set_fifo_ordering(uint32 fifo_ordering) { 238 void set_fifo_ordering(uint32 fifo_ordering) {
231 fifo_ordering_ = fifo_ordering; 239 fifo_ordering_ = fifo_ordering;
232 } 240 }
233 RequestClassification classification() const { 241 RequestClassification classification() const {
234 return classification_; 242 return classification_;
235 } 243 }
236 void set_classification(RequestClassification classification) { 244 void set_classification(RequestClassification classification) {
237 classification_ = classification; 245 classification_ = classification;
238 } 246 }
239 247
240 private: 248 private:
241 // ResourceMessageDelegate interface: 249 class UnownedPointer : public base::SupportsUserData::Data {
242 bool OnMessageReceived(const IPC::Message& message) override { 250 public:
243 bool handled = true; 251 explicit UnownedPointer(ScheduledResourceRequest* pointer)
244 IPC_BEGIN_MESSAGE_MAP(ScheduledResourceRequest, message) 252 : pointer_(pointer) {}
245 IPC_MESSAGE_HANDLER(ResourceHostMsg_DidChangePriority, DidChangePriority) 253
246 IPC_MESSAGE_UNHANDLED(handled = false) 254 ScheduledResourceRequest* get() const { return pointer_; }
247 IPC_END_MESSAGE_MAP() 255
248 return handled; 256 private:
249 } 257 ScheduledResourceRequest* const pointer_;
258
259 DISALLOW_COPY_AND_ASSIGN(UnownedPointer);
260 };
261
262 static const void* const kUserDataKey;
250 263
251 // ResourceThrottle interface: 264 // ResourceThrottle interface:
252 void WillStartRequest(bool* defer) override { 265 void WillStartRequest(bool* defer) override {
253 deferred_ = *defer = !ready_; 266 deferred_ = *defer = !ready_;
254 time_deferred_ = base::TimeTicks::Now(); 267 time_deferred_ = base::TimeTicks::Now();
255 } 268 }
256 269
257 const char* GetNameForLogging() const override { return "ResourceScheduler"; } 270 const char* GetNameForLogging() const override { return "ResourceScheduler"; }
258 271
259 void DidChangePriority(int request_id, net::RequestPriority new_priority,
260 int intra_priority_value) {
261 scheduler_->ReprioritizeRequest(this, new_priority, intra_priority_value);
262 }
263
264 const ClientId client_id_; 272 const ClientId client_id_;
265 const ResourceScheduler::ClientState client_state_on_creation_; 273 const ResourceScheduler::ClientState client_state_on_creation_;
266 net::URLRequest* request_; 274 net::URLRequest* request_;
267 bool ready_; 275 bool ready_;
268 bool deferred_; 276 bool deferred_;
277 bool is_async_;
269 RequestClassification classification_; 278 RequestClassification classification_;
270 ResourceScheduler* scheduler_; 279 ResourceScheduler* scheduler_;
271 RequestPriorityParams priority_; 280 RequestPriorityParams priority_;
272 uint32 fifo_ordering_; 281 uint32 fifo_ordering_;
273 base::TimeTicks time_deferred_; 282 base::TimeTicks time_deferred_;
274 283
275 DISALLOW_COPY_AND_ASSIGN(ScheduledResourceRequest); 284 DISALLOW_COPY_AND_ASSIGN(ScheduledResourceRequest);
276 }; 285 };
277 286
287 const void* const ResourceScheduler::ScheduledResourceRequest::kUserDataKey =
288 &ResourceScheduler::ScheduledResourceRequest::kUserDataKey;
289
278 bool ResourceScheduler::ScheduledResourceSorter::operator()( 290 bool ResourceScheduler::ScheduledResourceSorter::operator()(
279 const ScheduledResourceRequest* a, 291 const ScheduledResourceRequest* a,
280 const ScheduledResourceRequest* b) const { 292 const ScheduledResourceRequest* b) const {
281 // Want the set to be ordered first by decreasing priority, then by 293 // Want the set to be ordered first by decreasing priority, then by
282 // decreasing intra_priority. 294 // decreasing intra_priority.
283 // ie. with (priority, intra_priority) 295 // ie. with (priority, intra_priority)
284 // [(1, 0), (1, 0), (0, 100), (0, 0)] 296 // [(1, 0), (1, 0), (0, 100), (0, 0)]
285 if (a->get_request_priority_params() != b->get_request_priority_params()) 297 if (a->get_request_priority_params() != b->get_request_priority_params())
286 return a->get_request_priority_params().GreaterThan( 298 return a->get_request_priority_params().GreaterThan(
287 b->get_request_priority_params()); 299 b->get_request_priority_params());
(...skipping 30 matching lines...) Expand all
318 330
319 ~Client() { 331 ~Client() {
320 // Update to default state and pause to ensure the scheduler has a 332 // Update to default state and pause to ensure the scheduler has a
321 // correct count of relevant types of clients. 333 // correct count of relevant types of clients.
322 is_visible_ = false; 334 is_visible_ = false;
323 is_audible_ = false; 335 is_audible_ = false;
324 is_paused_ = true; 336 is_paused_ = true;
325 UpdateThrottleState(); 337 UpdateThrottleState();
326 } 338 }
327 339
328 void ScheduleRequest( 340 void ScheduleRequest(net::URLRequest* url_request,
329 net::URLRequest* url_request, 341 ScheduledResourceRequest* request) {
330 ScheduledResourceRequest* request) {
331 if (ShouldStartRequest(request) == START_REQUEST) 342 if (ShouldStartRequest(request) == START_REQUEST)
332 StartRequest(request); 343 StartRequest(request);
333 else 344 else
334 pending_requests_.Insert(request); 345 pending_requests_.Insert(request);
335 SetRequestClassification(request, ClassifyRequest(request)); 346 SetRequestClassification(request, ClassifyRequest(request));
336 } 347 }
337 348
338 void RemoveRequest(ScheduledResourceRequest* request) { 349 void RemoveRequest(ScheduledResourceRequest* request) {
339 if (pending_requests_.IsQueued(request)) { 350 if (pending_requests_.IsQueued(request)) {
340 pending_requests_.Erase(request); 351 pending_requests_.Erase(request);
(...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after
716 // * Non-delayable requests are issued imediately. 727 // * Non-delayable requests are issued imediately.
717 // * On a (currently 5 second) heart beat, they load all requests as an 728 // * On a (currently 5 second) heart beat, they load all requests as an
718 // UNTHROTTLED Client, and then return to the COALESCED state. 729 // UNTHROTTLED Client, and then return to the COALESCED state.
719 // * When an active Client makes a request, they are THROTTLED until the 730 // * When an active Client makes a request, they are THROTTLED until the
720 // active Client finishes loading. 731 // active Client finishes loading.
721 ShouldStartReqResult ShouldStartRequest( 732 ShouldStartReqResult ShouldStartRequest(
722 ScheduledResourceRequest* request) const { 733 ScheduledResourceRequest* request) const {
723 const net::URLRequest& url_request = *request->url_request(); 734 const net::URLRequest& url_request = *request->url_request();
724 // Syncronous requests could block the entire render, which could impact 735 // Syncronous requests could block the entire render, which could impact
725 // user-observable Clients. 736 // user-observable Clients.
726 if (!ResourceRequestInfo::ForRequest(&url_request)->IsAsync()) { 737 if (!request->is_async()) {
727 return START_REQUEST; 738 return START_REQUEST;
728 } 739 }
729 740
730 // TODO(simonjam): This may end up causing disk contention. We should 741 // TODO(simonjam): This may end up causing disk contention. We should
731 // experiment with throttling if that happens. 742 // experiment with throttling if that happens.
732 // TODO(aiolos): We probably want to Coalesce these as well to avoid 743 // TODO(aiolos): We probably want to Coalesce these as well to avoid
733 // waking the disk. 744 // waking the disk.
734 if (!url_request.url().SchemeIsHTTPOrHTTPS()) { 745 if (!url_request.url().SchemeIsHTTPOrHTTPS()) {
735 return START_REQUEST; 746 return START_REQUEST;
736 } 747 }
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
901 ResourceScheduler::ClientThrottleState 912 ResourceScheduler::ClientThrottleState
902 ResourceScheduler::GetClientStateForTesting(int child_id, int route_id) { 913 ResourceScheduler::GetClientStateForTesting(int child_id, int route_id) {
903 Client* client = GetClient(child_id, route_id); 914 Client* client = GetClient(child_id, route_id);
904 DCHECK(client); 915 DCHECK(client);
905 return client->throttle_state(); 916 return client->throttle_state();
906 } 917 }
907 918
908 scoped_ptr<ResourceThrottle> ResourceScheduler::ScheduleRequest( 919 scoped_ptr<ResourceThrottle> ResourceScheduler::ScheduleRequest(
909 int child_id, 920 int child_id,
910 int route_id, 921 int route_id,
922 bool is_async,
911 net::URLRequest* url_request) { 923 net::URLRequest* url_request) {
912 DCHECK(CalledOnValidThread()); 924 DCHECK(CalledOnValidThread());
913 ClientId client_id = MakeClientId(child_id, route_id); 925 ClientId client_id = MakeClientId(child_id, route_id);
914 scoped_ptr<ScheduledResourceRequest> request(new ScheduledResourceRequest( 926 scoped_ptr<ScheduledResourceRequest> request(new ScheduledResourceRequest(
915 client_id, 927 client_id, url_request, this,
916 url_request, 928 RequestPriorityParams(url_request->priority(), 0), is_async));
917 this,
918 RequestPriorityParams(url_request->priority(), 0)));
919 929
920 ClientMap::iterator it = client_map_.find(client_id); 930 ClientMap::iterator it = client_map_.find(client_id);
921 if (it == client_map_.end()) { 931 if (it == client_map_.end()) {
922 // There are several ways this could happen: 932 // There are several ways this could happen:
923 // 1. <a ping> requests don't have a route_id. 933 // 1. <a ping> requests don't have a route_id.
924 // 2. Most unittests don't send the IPCs needed to register Clients. 934 // 2. Most unittests don't send the IPCs needed to register Clients.
925 // 3. The tab is closed while a RequestResource IPC is in flight. 935 // 3. The tab is closed while a RequestResource IPC is in flight.
926 unowned_requests_.insert(request.get()); 936 unowned_requests_.insert(request.get());
927 request->Start(); 937 request->Start();
928 return request.Pass(); 938 return request.Pass();
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after
1164 } 1174 }
1165 1175
1166 ResourceScheduler::ClientState ResourceScheduler::GetClientState( 1176 ResourceScheduler::ClientState ResourceScheduler::GetClientState(
1167 ClientId client_id) const { 1177 ClientId client_id) const {
1168 ClientMap::const_iterator client_it = client_map_.find(client_id); 1178 ClientMap::const_iterator client_it = client_map_.find(client_id);
1169 if (client_it == client_map_.end()) 1179 if (client_it == client_map_.end())
1170 return UNKNOWN; 1180 return UNKNOWN;
1171 return client_it->second->is_active() ? ACTIVE : BACKGROUND; 1181 return client_it->second->is_active() ? ACTIVE : BACKGROUND;
1172 } 1182 }
1173 1183
1174 void ResourceScheduler::ReprioritizeRequest(ScheduledResourceRequest* request, 1184 void ResourceScheduler::ReprioritizeRequest(net::URLRequest* request,
1175 net::RequestPriority new_priority, 1185 net::RequestPriority new_priority,
1176 int new_intra_priority_value) { 1186 int new_intra_priority_value) {
1177 if (request->url_request()->load_flags() & net::LOAD_IGNORE_LIMITS) { 1187 if (request->load_flags() & net::LOAD_IGNORE_LIMITS) {
1178 // We should not be re-prioritizing requests with the 1188 // We should not be re-prioritizing requests with the
1179 // IGNORE_LIMITS flag. 1189 // IGNORE_LIMITS flag.
1180 NOTREACHED(); 1190 NOTREACHED();
1181 return; 1191 return;
1182 } 1192 }
1193
1194 auto* scheduled_resource_request =
1195 ScheduledResourceRequest::ForRequest(request);
1196
1197 // Downloads don't use the resource scheduler.
1198 if (!scheduled_resource_request) {
1199 request->SetPriority(new_priority);
1200 return;
1201 }
1202
1183 RequestPriorityParams new_priority_params(new_priority, 1203 RequestPriorityParams new_priority_params(new_priority,
1184 new_intra_priority_value); 1204 new_intra_priority_value);
1185 RequestPriorityParams old_priority_params = 1205 RequestPriorityParams old_priority_params =
1186 request->get_request_priority_params(); 1206 scheduled_resource_request->get_request_priority_params();
1187 1207
1188 DCHECK(old_priority_params != new_priority_params); 1208 DCHECK(old_priority_params != new_priority_params);
1189 1209
1190 ClientMap::iterator client_it = client_map_.find(request->client_id()); 1210 ClientMap::iterator client_it =
1211 client_map_.find(scheduled_resource_request->client_id());
1191 if (client_it == client_map_.end()) { 1212 if (client_it == client_map_.end()) {
1192 // The client was likely deleted shortly before we received this IPC. 1213 // The client was likely deleted shortly before we received this IPC.
1193 request->url_request()->SetPriority(new_priority_params.priority); 1214 request->SetPriority(new_priority_params.priority);
1194 request->set_request_priority_params(new_priority_params); 1215 scheduled_resource_request->set_request_priority_params(
1216 new_priority_params);
1195 return; 1217 return;
1196 } 1218 }
1197 1219
1198 if (old_priority_params == new_priority_params) 1220 if (old_priority_params == new_priority_params)
1199 return; 1221 return;
1200 1222
1201 Client *client = client_it->second; 1223 Client *client = client_it->second;
1202 client->ReprioritizeRequest( 1224 client->ReprioritizeRequest(scheduled_resource_request, old_priority_params,
1203 request, old_priority_params, new_priority_params); 1225 new_priority_params);
1204 } 1226 }
1205 1227
1206 ResourceScheduler::ClientId ResourceScheduler::MakeClientId( 1228 ResourceScheduler::ClientId ResourceScheduler::MakeClientId(
1207 int child_id, int route_id) { 1229 int child_id, int route_id) {
1208 return (static_cast<ResourceScheduler::ClientId>(child_id) << 32) | route_id; 1230 return (static_cast<ResourceScheduler::ClientId>(child_id) << 32) | route_id;
1209 } 1231 }
1210 1232
1211 } // namespace content 1233 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/loader/resource_scheduler.h ('k') | content/browser/loader/resource_scheduler_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698