Index: content/browser/loader/resource_scheduler.cc |
diff --git a/content/browser/loader/resource_scheduler.cc b/content/browser/loader/resource_scheduler.cc |
index 6cc902ea561895a7c7216103c6146b5b7107ff68..82d96ab51622e5e236712cba9256d394a4544f53 100644 |
--- a/content/browser/loader/resource_scheduler.cc |
+++ b/content/browser/loader/resource_scheduler.cc |
@@ -7,7 +7,9 @@ |
#include "content/browser/loader/resource_scheduler.h" |
#include "base/metrics/field_trial.h" |
+#include "base/metrics/histogram.h" |
#include "base/stl_util.h" |
+#include "base/time/time.h" |
#include "content/common/resource_messages.h" |
#include "content/browser/loader/resource_message_delegate.h" |
#include "content/public/browser/resource_controller.h" |
@@ -23,6 +25,24 @@ |
namespace content { |
+namespace { |
+ |
+void PostHistogram(const char* base_name, |
+ const char* suffix, |
+ base::TimeDelta time) { |
+ std::string histogram_name = |
+ base::StringPrintf("ResourceScheduler.%s.%s", base_name, suffix); |
+ base::HistogramBase* histogram_counter = base::Histogram::FactoryTimeGet( |
+ histogram_name, |
+ base::TimeDelta::FromMilliseconds(1), |
+ base::TimeDelta::FromMinutes(5), |
+ 50, |
+ base::Histogram::kUmaTargetedHistogramFlag); |
+ histogram_counter->AddTime(time); |
+} |
+ |
+} // namespace |
+ |
static const size_t kCoalescedTimerPeriod = 5000; |
static const size_t kMaxNumDelayableRequestsPerClient = 10; |
static const size_t kMaxNumDelayableRequestsPerHost = 6; |
@@ -123,6 +143,7 @@ class ResourceScheduler::ScheduledResourceRequest |
const RequestPriorityParams& priority) |
: ResourceMessageDelegate(request), |
client_id_(client_id), |
+ client_state_on_creation_(scheduler->GetClientState(client_id_)), |
request_(request), |
ready_(false), |
deferred_(false), |
@@ -139,10 +160,34 @@ class ResourceScheduler::ScheduledResourceRequest |
void Start() { |
TRACE_EVENT_ASYNC_STEP_PAST0("net", "URLRequest", request_, "Queued"); |
ready_ = true; |
- if (deferred_ && request_->status().is_success()) { |
+ if (!request_->status().is_success()) |
+ return; |
+ base::TimeTicks time = base::TimeTicks::Now(); |
+ ClientState current_state = scheduler_->GetClientState(client_id_); |
+ // Note: the client state isn't perfectly accurate since it won't capture |
+ // tabs which have switched between active and background multiple times. |
+ // Ex: A tab with the following transitions Active -> Background -> Active |
+ // will be recorded as Active. |
+ const char* client_state = "Other"; |
+ if (current_state == client_state_on_creation_ && current_state == ACTIVE) { |
+ client_state = "Active"; |
+ } else if (current_state == client_state_on_creation_ && |
+ current_state == BACKGROUND) { |
+ client_state = "Background"; |
+ } |
+ |
+ base::TimeDelta time_was_deferred = base::TimeDelta::FromMicroseconds(0); |
+ if (deferred_) { |
deferred_ = false; |
controller()->Resume(); |
+ time_was_deferred = time - time_deferred_; |
} |
+ PostHistogram("RequestTimeDeferred", client_state, time_was_deferred); |
+ PostHistogram( |
+ "RequestTimeThrottled", client_state, time - request_->creation_time()); |
+ // TODO(aiolos): Remove one of the above histograms after gaining an |
+ // understanding of the difference between them and which one is more |
+ // interesting. |
} |
void set_request_priority_params(const RequestPriorityParams& priority) { |
@@ -177,7 +222,10 @@ class ResourceScheduler::ScheduledResourceRequest |
} |
// ResourceThrottle interface: |
- void WillStartRequest(bool* defer) override { deferred_ = *defer = !ready_; } |
+ void WillStartRequest(bool* defer) override { |
+ deferred_ = *defer = !ready_; |
+ time_deferred_ = base::TimeTicks::Now(); |
+ } |
const char* GetNameForLogging() const override { return "ResourceScheduler"; } |
@@ -186,7 +234,8 @@ class ResourceScheduler::ScheduledResourceRequest |
scheduler_->ReprioritizeRequest(this, new_priority, intra_priority_value); |
} |
- ClientId client_id_; |
+ const ClientId client_id_; |
+ const ResourceScheduler::ClientState client_state_on_creation_; |
net::URLRequest* request_; |
bool ready_; |
bool deferred_; |
@@ -194,6 +243,7 @@ class ResourceScheduler::ScheduledResourceRequest |
ResourceScheduler* scheduler_; |
RequestPriorityParams priority_; |
uint32 fifo_ordering_; |
+ base::TimeTicks time_deferred_; |
DISALLOW_COPY_AND_ASSIGN(ScheduledResourceRequest); |
}; |
@@ -754,9 +804,11 @@ scoped_ptr<ResourceThrottle> ResourceScheduler::ScheduleRequest( |
net::URLRequest* url_request) { |
DCHECK(CalledOnValidThread()); |
ClientId client_id = MakeClientId(child_id, route_id); |
- scoped_ptr<ScheduledResourceRequest> request( |
- new ScheduledResourceRequest(client_id, url_request, this, |
- RequestPriorityParams(url_request->priority(), 0))); |
+ scoped_ptr<ScheduledResourceRequest> request(new ScheduledResourceRequest( |
+ client_id, |
+ url_request, |
+ this, |
+ RequestPriorityParams(url_request->priority(), 0))); |
ClientMap::iterator it = client_map_.find(client_id); |
if (it == client_map_.end()) { |
@@ -998,6 +1050,14 @@ void ResourceScheduler::LoadCoalescedRequests() { |
} |
} |
+ResourceScheduler::ClientState ResourceScheduler::GetClientState( |
+ ClientId client_id) const { |
+ ClientMap::const_iterator client_it = client_map_.find(client_id); |
+ if (client_it == client_map_.end()) |
+ return UNKNOWN; |
+ return client_it->second->is_active() ? ACTIVE : BACKGROUND; |
+} |
+ |
void ResourceScheduler::ReprioritizeRequest(ScheduledResourceRequest* request, |
net::RequestPriority new_priority, |
int new_intra_priority_value) { |