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

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