| Index: chrome/browser/renderer_host/resource_dispatcher_host.cc
|
| ===================================================================
|
| --- chrome/browser/renderer_host/resource_dispatcher_host.cc (revision 9239)
|
| +++ chrome/browser/renderer_host/resource_dispatcher_host.cc (working copy)
|
| @@ -72,6 +72,11 @@
|
| // given time for a given request.
|
| static const int kMaxPendingDataMessages = 20;
|
|
|
| +// Maximum byte "cost" of all the outstanding requests for a renderer.
|
| +// See delcaration of |max_outstanding_requests_cost_per_process_| for details.
|
| +// This bound is 25MB, which allows for around 6000 outstanding requests.
|
| +static const int kMaxOutstandingRequestsCostPerProcess = 26214400;
|
| +
|
| // A ShutdownTask proxies a shutdown task from the UI thread to the IO thread.
|
| // It should be constructed on the UI thread and run in the IO thread.
|
| class ResourceDispatcherHost::ShutdownTask : public Task {
|
| @@ -135,7 +140,8 @@
|
| request_id_(-1),
|
| plugin_service_(PluginService::GetInstance()),
|
| method_runner_(this),
|
| - is_shutdown_(false) {
|
| + is_shutdown_(false),
|
| + max_outstanding_requests_cost_per_process_(kMaxOutstandingRequestsCostPerProcess) {
|
| }
|
|
|
| ResourceDispatcherHost::~ResourceDispatcherHost() {
|
| @@ -568,6 +574,14 @@
|
| }
|
| }
|
|
|
| +int ResourceDispatcherHost::GetOutstandingRequestsMemoryCost(
|
| + int render_process_host_id) const {
|
| + OutstandingRequestsMemoryCostMap::const_iterator entry =
|
| + outstanding_requests_memory_cost_map_.find(render_process_host_id);
|
| + return (entry == outstanding_requests_memory_cost_map_.end()) ?
|
| + 0 : entry->second;
|
| +}
|
| +
|
| void ResourceDispatcherHost::OnClosePageACK(int render_process_host_id,
|
| int request_id) {
|
| GlobalRequestID global_id(render_process_host_id, request_id);
|
| @@ -674,8 +688,14 @@
|
|
|
| void ResourceDispatcherHost::RemovePendingRequest(
|
| const PendingRequestList::iterator& iter) {
|
| + ExtraRequestInfo* info = ExtraInfoForRequest(iter->second);
|
| +
|
| + // Remove the memory credit that we added when pushing the request onto
|
| + // the pending list.
|
| + IncrementOutstandingRequestsMemoryCost(-1 * info->memory_cost,
|
| + info->render_process_host_id);
|
| +
|
| // Notify the login handler that this request object is going away.
|
| - ExtraRequestInfo* info = ExtraInfoForRequest(iter->second);
|
| if (info && info->login_handler)
|
| info->login_handler->OnRequestCancelled();
|
|
|
| @@ -823,10 +843,89 @@
|
| response.get());
|
| }
|
|
|
| +int ResourceDispatcherHost::IncrementOutstandingRequestsMemoryCost(
|
| + int cost, int render_process_host_id) {
|
| + // Retrieve the previous value (defaulting to 0 if not found).
|
| + OutstandingRequestsMemoryCostMap::iterator prev_entry =
|
| + outstanding_requests_memory_cost_map_.find(render_process_host_id);
|
| + int new_cost = 0;
|
| + if (prev_entry != outstanding_requests_memory_cost_map_.end())
|
| + new_cost = prev_entry->second;
|
| +
|
| + // Insert/update the total; delete entries when their value reaches 0.
|
| + new_cost += cost;
|
| + CHECK(new_cost >= 0);
|
| + if (new_cost == 0)
|
| + outstanding_requests_memory_cost_map_.erase(prev_entry);
|
| + else
|
| + outstanding_requests_memory_cost_map_[render_process_host_id] = new_cost;
|
| +
|
| + return new_cost;
|
| +}
|
| +
|
| +// static
|
| +int ResourceDispatcherHost::CalculateApproximateMemoryCost(
|
| + URLRequest* request) {
|
| + // The following fields should be a minor size contribution (experimentally
|
| + // on the order of 100). However since they are variable length, it could
|
| + // in theory be a sizeable contribution.
|
| + int strings_cost = request->extra_request_headers().size() +
|
| + request->original_url().spec().size() +
|
| + request->referrer().size() +
|
| + request->method().size();
|
| +
|
| + int upload_cost = 0;
|
| +
|
| + // TODO(eroman): don't enable the upload throttling until we have data
|
| + // showing what a reasonable limit is (restricting to 25MB of uploads may
|
| + // be too restrictive).
|
| +#if 0
|
| + // Sum all the (non-file) upload data attached to the request, if any.
|
| + if (request->has_upload()) {
|
| + const std::vector<net::UploadData::Element>& uploads =
|
| + request->get_upload()->elements();
|
| + std::vector<net::UploadData::Element>::const_iterator iter;
|
| + for (iter = uploads.begin(); iter != uploads.end(); ++iter) {
|
| + if (iter->type() == net::UploadData::TYPE_BYTES) {
|
| + int64 element_size = iter->GetContentLength();
|
| + // This cast should not result in truncation.
|
| + upload_cost += static_cast<int>(element_size);
|
| + }
|
| + }
|
| + }
|
| +#endif
|
| +
|
| + // Note that this expression will typically be dominated by:
|
| + // |kAvgBytesPerOutstandingRequest|.
|
| + return kAvgBytesPerOutstandingRequest + strings_cost + upload_cost;
|
| +}
|
| +
|
| void ResourceDispatcherHost::BeginRequestInternal(URLRequest* request,
|
| bool mixed_content) {
|
| + DCHECK(!request->is_pending());
|
| ExtraRequestInfo* info = ExtraInfoForRequest(request);
|
|
|
| + // Add the memory estimate that starting this request will consume.
|
| + info->memory_cost = CalculateApproximateMemoryCost(request);
|
| + int memory_cost = IncrementOutstandingRequestsMemoryCost(
|
| + info->memory_cost,
|
| + info->render_process_host_id);
|
| +
|
| + // If enqueing/starting this request will exceed our per-process memory
|
| + // bound, abort it right away.
|
| + if (memory_cost > max_outstanding_requests_cost_per_process_) {
|
| + // We call "CancelWithError()" as a way of setting the URLRequest's
|
| + // status -- it has no effect beyond this, since the request hasn't started.
|
| + request->CancelWithError(net::ERR_INSUFFICIENT_RESOURCES);
|
| +
|
| + // TODO(eroman): this is kinda funky -- we insert the unstarted request into
|
| + // |pending_requests_| simply to please OnResponseCompleted().
|
| + GlobalRequestID global_id(info->render_process_host_id, info->request_id);
|
| + pending_requests_[global_id] = request;
|
| + OnResponseCompleted(request);
|
| + return;
|
| + }
|
| +
|
| std::pair<int, int> pair_id(info->render_process_host_id,
|
| info->render_view_id);
|
| BlockedRequestMap::const_iterator iter = blocked_requests_map_.find(pair_id);
|
| @@ -1317,6 +1416,11 @@
|
|
|
| for (BlockedRequestsList::iterator req_iter = requests->begin();
|
| req_iter != requests->end(); ++req_iter) {
|
| + // Remove the memory credit that we added when pushing the request onto
|
| + // the blocked list.
|
| + ExtraRequestInfo* info = ExtraInfoForRequest(req_iter->url_request);
|
| + IncrementOutstandingRequestsMemoryCost(-1 * info->memory_cost,
|
| + info->render_process_host_id);
|
| if (cancel_requests)
|
| delete req_iter->url_request;
|
| else
|
|
|