Chromium Code Reviews| Index: chrome/browser/net/cache_stats.cc |
| =================================================================== |
| --- chrome/browser/net/cache_stats.cc (revision 150909) |
| +++ chrome/browser/net/cache_stats.cc (working copy) |
| @@ -22,6 +22,7 @@ |
| using content::BrowserThread; |
| using content::RenderViewHost; |
| using content::ResourceRequestInfo; |
| +using std::string; |
| #if defined(COMPILER_GCC) |
| @@ -72,6 +73,32 @@ |
| static int kTabLoadStatsAutoCleanupTimeoutSeconds = 30; |
| +const char* kRequestStatusNames[] = { |
| + "CacheWait", |
| + "NetworkWait", |
| + "Active", |
| + "None", |
| + "Max" |
| +}; |
| + |
| +COMPILE_ASSERT(arraysize(kRequestStatusNames) == |
| + chrome_browser_net::CacheStats::REQUEST_STATUS_MAX + 1, |
| + CacheStats_RequestStatus_names_mismatch); |
| + |
| +const char* kHistogramTypeNames[] = { |
| + "FinalAggregate", |
| + "FinalCumulative", |
| + "FinalCumulativePercentage", |
| + "IntermediateAggregate", |
| + "IntermediateCumulative", |
| + "IntermediateCumulativePercentage", |
| + "Max" |
| +}; |
| + |
| +COMPILE_ASSERT(arraysize(kHistogramTypeNames) == |
| + chrome_browser_net::CacheStats::HISTOGRAM_MAX + 1, |
| + CacheStats_HistogramType_names_mismatch); |
| + |
| } // namespace |
| namespace chrome_browser_net { |
| @@ -82,7 +109,6 @@ |
| struct CacheStats::TabLoadStats { |
| TabLoadStats(std::pair<int, int> render_view_id, CacheStats* owner) |
| : render_view_id(render_view_id), |
| - num_active(0), |
| spinner_started(false), |
| next_timer_index(0), |
| timer(false, false) { |
| @@ -100,16 +126,37 @@ |
| render_view_id)); |
| } |
| + struct PerRequestStatusData { |
|
rvargas (doing something else)
2012/08/15 22:36:50
This should be a class, and it needs a description
tburkard
2012/08/15 23:00:47
Description has been added. This only contains PO
rvargas (doing something else)
2012/08/16 01:18:40
The type of members is actually not important when
tburkard
2012/08/16 22:37:43
Done.
|
| + PerRequestStatusData() |
| + : num_active(0) { |
| + } |
| + void UpdateTotalTimes() { |
| + base::TimeTicks now = base::TimeTicks::Now(); |
| + if (num_active > 0) { |
| + total_time += now - current_start_time; |
| + total_cumulative_time += |
| + (now - current_start_time) * static_cast<int64>(num_active); |
| + } |
| + current_start_time = now; |
| + } |
| + void ResetTimes() { |
| + current_start_time = base::TimeTicks::Now(); |
| + total_time = base::TimeDelta(); |
| + total_cumulative_time = base::TimeDelta(); |
| + } |
| + int num_active; |
| + base::TimeTicks current_start_time; |
| + base::TimeDelta total_time; |
| + base::TimeDelta total_cumulative_time; |
| + }; |
| std::pair<int, int> render_view_id; |
| - int num_active; |
| + PerRequestStatusData per_status_stats[REQUEST_STATUS_MAX]; |
| bool spinner_started; |
| base::TimeTicks load_start_time; |
| - base::TimeTicks cache_start_time; |
| - base::TimeDelta cache_total_time; |
| int next_timer_index; |
| base::Timer timer; |
| - // URLRequest's for which there are outstanding cache transactions. |
| - base::hash_set<const net::URLRequest*> active_requests; |
| + // Currently active URLRequests. |
| + base::hash_map<const net::URLRequest*, RequestStatus> active_requests; |
| }; |
| CacheStatsTabHelper::CacheStatsTabHelper(TabContents* tab) |
| @@ -155,23 +202,38 @@ |
| } |
| CacheStats::CacheStats() { |
| - for (int i = 0; |
| - i < static_cast<int>(arraysize(kStatsCollectionTimesMs)); |
| - i++) { |
| - final_histograms_.push_back( |
| - base::LinearHistogram::FactoryGet( |
| - "CacheStats.FractionCacheUseFinalPLT_" + |
| - base::IntToString(kStatsCollectionTimesMs[i]), |
| - 0, 101, 102, base::Histogram::kUmaTargetedHistogramFlag)); |
| - intermediate_histograms_.push_back( |
| - base::LinearHistogram::FactoryGet( |
| - "CacheStats.FractionCacheUseIntermediatePLT_" + |
| - base::IntToString(kStatsCollectionTimesMs[i]), |
| - 0, 101, 102, base::Histogram::kUmaTargetedHistogramFlag)); |
| + for (int status_int = REQUEST_STATUS_CACHE_WAIT; |
| + status_int <= REQUEST_STATUS_ACTIVE; |
| + status_int++) { |
| + RequestStatus status = static_cast<RequestStatus>(status_int); |
| + for (int type_int = HISTOGRAM_FINAL_AGGREGATE; |
| + type_int < HISTOGRAM_MAX; |
| + type_int++) { |
| + HistogramType type = static_cast<HistogramType>(type_int); |
| + for (int i = 0; |
| + i < static_cast<int>(arraysize(kStatsCollectionTimesMs)); |
| + i++) { |
| + string histogram_name = string("CacheStats.Fraction_") + |
| + string(kRequestStatusNames[status]) + string("_") + |
| + string(kHistogramTypeNames[type]) + string("_") + |
| + base::IntToString(kStatsCollectionTimesMs[i]); |
| + if (type != HISTOGRAM_FINAL_CUMULATIVE_PERCENTAGE && |
| + type != HISTOGRAM_INTERMEDIATE_CUMULATIVE_PERCENTAGE) { |
| + histograms_[status][type].push_back( |
| + base::LinearHistogram::FactoryGet( |
| + histogram_name, |
| + 0, 101, 102, base::Histogram::kUmaTargetedHistogramFlag)); |
| + } else { |
| + histograms_[status][type].push_back( |
| + base::Histogram::FactoryGet( |
| + histogram_name, |
| + 0, 10000, 500, base::Histogram::kUmaTargetedHistogramFlag)); |
| + } |
| + } |
| + DCHECK_EQ(histograms_[status][type].size(), |
| + arraysize(kStatsCollectionTimesMs)); |
| + } |
| } |
| - DCHECK_EQ(final_histograms_.size(), arraysize(kStatsCollectionTimesMs)); |
| - DCHECK_EQ(intermediate_histograms_.size(), |
| - arraysize(kStatsCollectionTimesMs)); |
| } |
| CacheStats::~CacheStats() { |
| @@ -196,9 +258,9 @@ |
| } |
| } |
| -void CacheStats::OnCacheWaitStateChange( |
| +void CacheStats::OnRequestWaitStateChange( |
| const net::URLRequest& request, |
| - net::NetworkDelegate::CacheWaitState state) { |
| + net::NetworkDelegate::RequestWaitState state) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| if (main_request_contexts_.count(request.context()) < 1) |
| return; |
| @@ -207,44 +269,57 @@ |
| return; |
| TabLoadStats* stats = |
| GetTabLoadStats(std::pair<int, int>(process_id, route_id)); |
| - bool newly_started = false; |
| - bool newly_finished = false; |
| + RequestStatus old_status = REQUEST_STATUS_NONE; |
| + if (stats->active_requests.count(&request) > 0) |
| + old_status = stats->active_requests[&request]; |
| + RequestStatus new_status = REQUEST_STATUS_NONE; |
| switch (state) { |
| - case net::NetworkDelegate::CACHE_WAIT_STATE_START: |
| - DCHECK(stats->active_requests.count(&request) == 0); |
| - newly_started = true; |
| - stats->active_requests.insert(&request); |
| + case net::NetworkDelegate::REQUEST_WAIT_STATE_CACHE_START: |
| + DCHECK(old_status == REQUEST_STATUS_NONE || |
| + old_status == REQUEST_STATUS_ACTIVE); |
| + new_status = REQUEST_STATUS_CACHE_WAIT; |
| break; |
| - case net::NetworkDelegate::CACHE_WAIT_STATE_FINISH: |
| - if (stats->active_requests.count(&request) > 0) { |
| - stats->active_requests.erase(&request); |
| - newly_finished = true; |
| - } |
| + case net::NetworkDelegate::REQUEST_WAIT_STATE_CACHE_FINISH: |
| + DCHECK(old_status == REQUEST_STATUS_NONE || |
| + old_status == REQUEST_STATUS_CACHE_WAIT); |
| + new_status = REQUEST_STATUS_ACTIVE; |
| break; |
| - case net::NetworkDelegate::CACHE_WAIT_STATE_RESET: |
| - if (stats->active_requests.count(&request) > 0) { |
| - stats->active_requests.erase(&request); |
| - newly_finished = true; |
| - } |
| + case net::NetworkDelegate::REQUEST_WAIT_STATE_NETWORK_START: |
| + DCHECK(old_status == REQUEST_STATUS_NONE || |
| + old_status == REQUEST_STATUS_ACTIVE); |
| + new_status = REQUEST_STATUS_NETWORK_WAIT; |
| break; |
| + case net::NetworkDelegate::REQUEST_WAIT_STATE_NETWORK_FINISH: |
| + DCHECK(old_status == REQUEST_STATUS_NONE || |
| + old_status == REQUEST_STATUS_NETWORK_WAIT); |
| + new_status = REQUEST_STATUS_ACTIVE; |
| + break; |
| + case net::NetworkDelegate::REQUEST_WAIT_STATE_RESET: |
| + new_status = REQUEST_STATUS_NONE; |
| + break; |
| } |
| - DCHECK_GE(stats->num_active, 0); |
| - if (newly_started) { |
| - DCHECK(!newly_finished); |
| - if (stats->num_active == 0) { |
| - stats->cache_start_time = base::TimeTicks::Now(); |
| + if (old_status != new_status) { |
| + for (int status_int = REQUEST_STATUS_CACHE_WAIT; |
| + status_int <= REQUEST_STATUS_ACTIVE; status_int++) { |
| + RequestStatus status = static_cast<RequestStatus>(status_int); |
| + TabLoadStats::PerRequestStatusData* status_stats = |
| + &(stats->per_status_stats[status]); |
| + DCHECK_GE(status_stats->num_active, 0); |
| + if (old_status == status) { |
| + status_stats->UpdateTotalTimes(); |
| + status_stats->num_active--; |
| + } |
| + if (new_status == status) { |
| + status_stats->UpdateTotalTimes(); |
| + status_stats->num_active++; |
| + } |
| + DCHECK_GE(status_stats->num_active, 0); |
| } |
| - stats->num_active++; |
| } |
| - if (newly_finished) { |
| - DCHECK(!newly_started); |
| - if (stats->num_active == 1) { |
| - stats->cache_total_time += |
| - base::TimeTicks::Now() - stats->cache_start_time; |
| - } |
| - stats->num_active--; |
| - } |
| - DCHECK_GE(stats->num_active, 0); |
| + if (new_status == REQUEST_STATUS_NONE) |
| + stats->active_requests.erase(&request); |
| + else |
| + stats->active_requests[&request] = new_status; |
| } |
| void CacheStats::OnTabEvent(std::pair<int, int> render_view_id, |
| @@ -253,9 +328,11 @@ |
| TabLoadStats* stats = GetTabLoadStats(render_view_id); |
| if (event == SPINNER_START) { |
| stats->spinner_started = true; |
| - stats->cache_total_time = base::TimeDelta(); |
| - stats->cache_start_time = base::TimeTicks::Now(); |
| - stats->load_start_time = base::TimeTicks::Now(); |
| + for (int status_int = REQUEST_STATUS_CACHE_WAIT; |
| + status_int <= REQUEST_STATUS_ACTIVE; status_int++) { |
| + RequestStatus status = static_cast<RequestStatus>(status_int); |
| + stats->per_status_stats[status].ResetTimes(); |
| + } |
| stats->next_timer_index = 0; |
| ScheduleTimer(stats); |
| } else { |
| @@ -264,11 +341,7 @@ |
| stats->spinner_started = false; |
| base::TimeDelta load_time = |
| base::TimeTicks::Now() - stats->load_start_time; |
| - if (stats->num_active > 1) |
| - stats->cache_total_time += |
| - base::TimeTicks::Now() - stats->cache_start_time; |
| - RecordCacheFractionHistogram(load_time, stats->cache_total_time, true, |
| - stats->next_timer_index); |
| + RecordHistograms(load_time, stats, true); |
| } |
| RemoveTabLoadStats(render_view_id); |
| } |
| @@ -299,11 +372,7 @@ |
| void CacheStats::TimerCallback(TabLoadStats* stats) { |
| DCHECK(stats->spinner_started); |
| base::TimeDelta load_time = base::TimeTicks::Now() - stats->load_start_time; |
| - base::TimeDelta cache_time = stats->cache_total_time; |
| - if (stats->num_active > 1) |
| - cache_time += base::TimeTicks::Now() - stats->cache_start_time; |
| - RecordCacheFractionHistogram(load_time, cache_time, false, |
| - stats->next_timer_index); |
| + RecordHistograms(load_time, stats, false); |
| stats->next_timer_index++; |
| if (stats->next_timer_index < |
| static_cast<int>(arraysize(kStatsCollectionTimesMs))) { |
| @@ -313,25 +382,67 @@ |
| } |
| } |
| -void CacheStats::RecordCacheFractionHistogram(base::TimeDelta elapsed, |
| - base::TimeDelta cache_time, |
| - bool is_load_done, |
| - int timer_index) { |
| +void CacheStats::RecordHistograms(base::TimeDelta elapsed, |
| + TabLoadStats* stats, |
| + bool is_load_done) { |
| + int timer_index = stats->next_timer_index; |
| DCHECK(timer_index >= 0 && |
| timer_index < static_cast<int>(arraysize(kStatsCollectionTimesMs))); |
| if (elapsed.InMilliseconds() <= 0) |
| return; |
| - int64 cache_fraction_percentage = |
| - 100 * cache_time.InMilliseconds() / elapsed.InMilliseconds(); |
| + base::TimeDelta total_cumulative; |
| + for (int status_int = REQUEST_STATUS_CACHE_WAIT; |
| + status_int <= REQUEST_STATUS_ACTIVE; |
| + status_int++) { |
| + RequestStatus status = static_cast<RequestStatus>(status_int); |
| + total_cumulative += stats->per_status_stats[status].total_cumulative_time; |
| + } |
| - DCHECK(cache_fraction_percentage >= 0 && cache_fraction_percentage <= 100); |
| + for (int status_int = REQUEST_STATUS_CACHE_WAIT; |
| + status_int <= REQUEST_STATUS_ACTIVE; |
| + status_int++) { |
| + RequestStatus status = static_cast<RequestStatus>(status_int); |
| + TabLoadStats::PerRequestStatusData* status_stats = |
| + &(stats->per_status_stats[status]); |
| - if (is_load_done) { |
| - final_histograms_[timer_index]->Add(cache_fraction_percentage); |
| - } else { |
| - intermediate_histograms_[timer_index]->Add(cache_fraction_percentage); |
| + int64 fraction_percentage = 100 * |
| + status_stats->total_time.InMilliseconds() / elapsed.InMilliseconds(); |
| + DCHECK(fraction_percentage >= 0 && fraction_percentage <= 100); |
| + if (is_load_done) { |
| + histograms_[status][HISTOGRAM_FINAL_AGGREGATE][timer_index]->Add( |
| + fraction_percentage); |
| + } else { |
| + histograms_[status][HISTOGRAM_INTERMEDIATE_AGGREGATE][timer_index]->Add( |
| + fraction_percentage); |
| + } |
| + |
| + fraction_percentage = 100 * |
| + status_stats->total_cumulative_time.InMilliseconds() / |
| + elapsed.InMilliseconds(); |
| + DCHECK(fraction_percentage >= 0); |
| + if (is_load_done) { |
| + histograms_[status][HISTOGRAM_FINAL_CUMULATIVE][timer_index]->Add( |
| + fraction_percentage); |
| + } else { |
| + histograms_[status][HISTOGRAM_INTERMEDIATE_CUMULATIVE][timer_index]->Add( |
| + fraction_percentage); |
| + } |
| + |
| + if (total_cumulative.InMilliseconds() > 0) { |
| + fraction_percentage = 100 * |
| + status_stats->total_cumulative_time.InMilliseconds() / |
| + total_cumulative.InMilliseconds(); |
| + DCHECK(fraction_percentage >= 0 && fraction_percentage <= 100); |
| + if (is_load_done) { |
| + histograms_[status][HISTOGRAM_FINAL_CUMULATIVE_PERCENTAGE] |
| + [timer_index]->Add(fraction_percentage); |
| + } else { |
| + histograms_[status][HISTOGRAM_INTERMEDIATE_CUMULATIVE_PERCENTAGE] |
| + [timer_index]->Add(fraction_percentage); |
| + } |
| + } |
| } |
| } |