Index: content/browser/loader/resource_dispatcher_host_impl.cc |
diff --git a/content/browser/loader/resource_dispatcher_host_impl.cc b/content/browser/loader/resource_dispatcher_host_impl.cc |
index 39108877eb551027f55ebfd7e6d29a13dc89690d..71b316f31a1577be7f78ae2ae946034ac85103fc 100644 |
--- a/content/browser/loader/resource_dispatcher_host_impl.cc |
+++ b/content/browser/loader/resource_dispatcher_host_impl.cc |
@@ -78,6 +78,7 @@ |
#include "content/common/resource_request.h" |
#include "content/common/resource_request_body_impl.h" |
#include "content/common/resource_request_completion_status.h" |
+#include "content/common/site_isolation_policy.h" |
#include "content/common/view_messages.h" |
#include "content/public/browser/browser_thread.h" |
#include "content/public/browser/global_request_id.h" |
@@ -168,6 +169,9 @@ static ResourceDispatcherHostImpl* g_resource_dispatcher_host; |
// The interval for calls to ResourceDispatcherHostImpl::UpdateLoadStates |
const int kUpdateLoadStatesIntervalMsec = 250; |
+// The interval for calls to RecordOutstandingRequestsStats. |
+const int kRecordOutstandingRequestsStatsIntervalMsec = 60000; |
+ |
// Maximum byte "cost" of all the outstanding requests for a renderer. |
// See declaration of |max_outstanding_requests_cost_per_process_| for details. |
// This bound is 25MB, which allows for around 6000 outstanding requests. |
@@ -339,6 +343,8 @@ ResourceDispatcherHostImpl::ResourceDispatcherHostImpl( |
kMaxOutstandingRequestsCostPerProcess), |
largest_outstanding_request_count_seen_(0), |
largest_outstanding_request_per_process_count_seen_(0), |
+ peak_outstanding_request_count_(0), |
Charlie Harrison
2017/06/22 12:33:46
These aren't necessary if they are declared in the
Kunihiko Sakamoto
2017/06/23 04:22:06
Done.
|
+ peak_outstanding_request_count_multitab_(0), |
delegate_(nullptr), |
loader_delegate_(nullptr), |
allow_cross_origin_auth_prompt_(false), |
@@ -361,6 +367,7 @@ ResourceDispatcherHostImpl::ResourceDispatcherHostImpl( |
base::Bind(&ResourceDispatcherHostImpl::OnInit, base::Unretained(this))); |
update_load_states_timer_.reset(new base::RepeatingTimer()); |
+ record_outstanding_requests_stats_timer_.reset(new base::RepeatingTimer()); |
Charlie Harrison
2017/06/22 12:33:46
nit: prefer base::MakeUnique to avoid bare new.
Kunihiko Sakamoto
2017/06/23 04:22:06
Done.
|
} |
// The default ctor is only used by unittests. It is reasonable to assume that |
@@ -371,6 +378,7 @@ ResourceDispatcherHostImpl::ResourceDispatcherHostImpl() |
ResourceDispatcherHostImpl::~ResourceDispatcherHostImpl() { |
DCHECK(outstanding_requests_stats_map_.empty()); |
+ DCHECK(outstanding_requests_per_tab_map_.empty()); |
DCHECK(g_resource_dispatcher_host); |
DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); |
g_resource_dispatcher_host = NULL; |
@@ -589,13 +597,20 @@ bool ResourceDispatcherHostImpl::HandleExternalProtocol(ResourceLoader* loader, |
} |
void ResourceDispatcherHostImpl::DidStartRequest(ResourceLoader* loader) { |
- // Make sure we have the load state monitor running. |
+ // Make sure we have the load state monitors running. |
if (!update_load_states_timer_->IsRunning() && |
scheduler_->HasLoadingClients()) { |
update_load_states_timer_->Start( |
FROM_HERE, TimeDelta::FromMilliseconds(kUpdateLoadStatesIntervalMsec), |
this, &ResourceDispatcherHostImpl::UpdateLoadInfo); |
} |
+ if (!record_outstanding_requests_stats_timer_->IsRunning()) { |
+ record_outstanding_requests_stats_timer_->Start( |
+ FROM_HERE, |
+ TimeDelta::FromMilliseconds( |
+ kRecordOutstandingRequestsStatsIntervalMsec), |
+ this, &ResourceDispatcherHostImpl::RecordOutstandingRequestsStats); |
+ } |
} |
void ResourceDispatcherHostImpl::DidReceiveRedirect( |
@@ -784,10 +799,11 @@ void ResourceDispatcherHostImpl::OnShutdown() { |
is_shutdown_ = true; |
pending_loaders_.clear(); |
- // Make sure we shutdown the timer now, otherwise by the time our destructor |
+ // Make sure we shutdown the timers now, otherwise by the time our destructor |
// runs if the timer is still running the Task is deleted twice (once by |
// the MessageLoop and the second time by RepeatingTimer). |
update_load_states_timer_.reset(); |
+ record_outstanding_requests_stats_timer_.reset(); |
// Clear blocked requests if any left. |
// Note that we have to do this in 2 passes as we cannot call |
@@ -1919,6 +1935,26 @@ void ResourceDispatcherHostImpl::UpdateOutstandingRequestsStats( |
outstanding_requests_stats_map_[info.GetChildID()] = stats; |
} |
+void ResourceDispatcherHostImpl::IncrementOutstandingRequestsPerTab( |
+ int count, |
+ const ResourceRequestInfoImpl& info) { |
+ // No-op in OOPIF modes, because the routing id doesn't represent tabs. |
Charlie Harrison
2017/06/22 12:33:46
Can we just not initialize the timer in these case
Kunihiko Sakamoto
2017/06/23 04:22:06
Done.
|
+ if (SiteIsolationPolicy::UseDedicatedProcessesForAllSites() || |
+ SiteIsolationPolicy::IsTopDocumentIsolationEnabled() || |
+ SiteIsolationPolicy::AreIsolatedOriginsEnabled()) { |
+ return; |
+ } |
+ |
+ auto key = std::make_pair(info.GetChildID(), info.GetRouteID()); |
+ OutstandingRequestsPerTabMap::iterator entry = |
+ outstanding_requests_per_tab_map_.insert(std::make_pair(key, 0)).first; |
+ entry->second += count; |
+ DCHECK_GE(entry->second, 0); |
+ if (entry->second == 0) { |
+ outstanding_requests_per_tab_map_.erase(entry); |
+ } |
+} |
+ |
ResourceDispatcherHostImpl::OustandingRequestsStats |
ResourceDispatcherHostImpl::IncrementOutstandingRequestsMemory( |
int count, |
@@ -1954,6 +1990,8 @@ ResourceDispatcherHostImpl::IncrementOutstandingRequestsCount( |
DCHECK_GE(stats.num_requests, 0); |
UpdateOutstandingRequestsStats(*info, stats); |
+ IncrementOutstandingRequestsPerTab(count, *info); |
+ |
if (num_in_flight_requests_ > largest_outstanding_request_count_seen_) { |
largest_outstanding_request_count_seen_ = num_in_flight_requests_; |
UMA_HISTOGRAM_COUNTS_1M( |
@@ -1969,6 +2007,15 @@ ResourceDispatcherHostImpl::IncrementOutstandingRequestsCount( |
largest_outstanding_request_per_process_count_seen_); |
} |
+ if (num_in_flight_requests_ > peak_outstanding_request_count_) { |
+ peak_outstanding_request_count_ = num_in_flight_requests_; |
+ } |
+ |
+ if (HasRequestsFromMultipleActiveTabs() && |
+ num_in_flight_requests_ > peak_outstanding_request_count_multitab_) { |
+ peak_outstanding_request_count_multitab_ = num_in_flight_requests_; |
+ } |
+ |
return stats; |
} |
@@ -2497,6 +2544,23 @@ void ResourceDispatcherHostImpl::UpdateLoadInfo() { |
base::Bind(UpdateLoadStateOnUI, loader_delegate_, base::Passed(&infos))); |
} |
+void ResourceDispatcherHostImpl::RecordOutstandingRequestsStats() { |
+ if (peak_outstanding_request_count_ != 0) { |
+ UMA_HISTOGRAM_COUNTS_1M( |
+ "Net.ResourceDispatcherHost.PeakOutstandingRequests", |
+ peak_outstanding_request_count_); |
+ peak_outstanding_request_count_ = num_in_flight_requests_; |
+ } |
+ |
+ if (peak_outstanding_request_count_multitab_ != 0) { |
+ UMA_HISTOGRAM_COUNTS_1M( |
+ "Net.ResourceDispatcherHost.PeakOutstandingRequests.MultiTabLoading", |
+ peak_outstanding_request_count_multitab_); |
+ peak_outstanding_request_count_multitab_ = |
+ HasRequestsFromMultipleActiveTabs() ? num_in_flight_requests_ : 0; |
+ } |
+} |
+ |
void ResourceDispatcherHostImpl::BlockRequestsForRoute( |
const GlobalFrameRoutingId& global_routing_id) { |
DCHECK(io_thread_task_runner_->BelongsToCurrentThread()); |
@@ -2706,4 +2770,21 @@ ResourceDispatcherHostImpl::HandleDownloadStarted( |
return handler; |
} |
+bool ResourceDispatcherHostImpl::HasRequestsFromMultipleActiveTabs() { |
+ if (outstanding_requests_per_tab_map_.size() < 2) |
+ return false; |
+ |
+ int active_tabs = 0; |
+ for (auto iter = outstanding_requests_per_tab_map_.begin(); |
+ iter != outstanding_requests_per_tab_map_.end(); ++iter) { |
+ if (iter->second > 2) { |
+ active_tabs++; |
+ if (active_tabs >= 2) { |
+ return true; |
+ } |
+ } |
+ } |
+ return false; |
+} |
+ |
} // namespace content |