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

Side by Side Diff: chrome/browser/net/load_time_stats.cc

Issue 10834313: Add histograms for network activity, and total/cumulative (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 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 | Annotate | Revision Log
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 "chrome/browser/net/cache_stats.h" 5 #include "chrome/browser/net/load_time_stats.h"
6 6
7 #include "base/metrics/histogram.h" 7 #include "base/metrics/histogram.h"
8 #include "base/stl_util.h" 8 #include "base/stl_util.h"
9 #include "base/string_number_conversions.h" 9 #include "base/string_number_conversions.h"
10 #include "base/timer.h" 10 #include "base/timer.h"
11 #include "chrome/browser/browser_process.h" 11 #include "chrome/browser/browser_process.h"
12 #include "chrome/browser/io_thread.h" 12 #include "chrome/browser/io_thread.h"
13 #include "chrome/browser/profiles/profile.h" 13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/browser/ui/tab_contents/tab_contents.h" 14 #include "chrome/browser/ui/tab_contents/tab_contents.h"
15 #include "content/public/browser/browser_thread.h" 15 #include "content/public/browser/browser_thread.h"
16 #include "content/public/browser/render_process_host.h" 16 #include "content/public/browser/render_process_host.h"
17 #include "content/public/browser/render_view_host.h" 17 #include "content/public/browser/render_view_host.h"
18 #include "content/public/browser/resource_request_info.h" 18 #include "content/public/browser/resource_request_info.h"
19 #include "content/public/browser/web_contents.h" 19 #include "content/public/browser/web_contents.h"
20 #include "net/url_request/url_request.h" 20 #include "net/url_request/url_request.h"
21 21
22 using content::BrowserThread; 22 using content::BrowserThread;
23 using content::RenderViewHost; 23 using content::RenderViewHost;
24 using content::ResourceRequestInfo; 24 using content::ResourceRequestInfo;
25 using std::string;
25 26
26 #if defined(COMPILER_GCC) 27 #if defined(COMPILER_GCC)
27 28
28 namespace BASE_HASH_NAMESPACE { 29 namespace BASE_HASH_NAMESPACE {
29 template <> 30 template <>
30 struct hash<const net::URLRequest*> { 31 struct hash<const net::URLRequest*> {
31 std::size_t operator()(const net::URLRequest* value) const { 32 std::size_t operator()(const net::URLRequest* value) const {
32 return reinterpret_cast<std::size_t>(value); 33 return reinterpret_cast<std::size_t>(value);
33 } 34 }
34 }; 35 };
35 } 36 }
36 37
37 #endif 38 #endif
38 39
39 namespace { 40 namespace {
40 41
41 bool GetRenderView(const net::URLRequest& request, 42 bool GetRenderView(const net::URLRequest& request,
42 int* process_id, int* route_id) { 43 int* process_id, int* route_id) {
43 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 44 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
44 const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(&request); 45 const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(&request);
45 if (!info) 46 if (!info)
46 return false; 47 return false;
47 return info->GetAssociatedRenderView(process_id, route_id); 48 return info->GetAssociatedRenderView(process_id, route_id);
48 } 49 }
49 50
50 void CallCacheStatsTabEventOnIOThread( 51 void CallLoadTimeStatsTabEventOnIOThread(
51 std::pair<int, int> render_view_id, 52 std::pair<int, int> render_view_id,
52 chrome_browser_net::CacheStats::TabEvent event, 53 chrome_browser_net::LoadTimeStats::TabEvent event,
53 IOThread* io_thread) { 54 IOThread* io_thread) {
54 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 55 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
55 if (io_thread) 56 if (io_thread)
56 io_thread->globals()->cache_stats->OnTabEvent(render_view_id, event); 57 io_thread->globals()->load_time_stats->OnTabEvent(render_view_id, event);
57 } 58 }
58 59
59 // Times after a load has started at which stats are collected. 60 // Times after a load has started at which stats are collected.
60 const int kStatsCollectionTimesMs[] = { 61 const int kStatsCollectionTimesMs[] = {
61 500, 62 500,
62 1000, 63 1000,
63 2000, 64 2000,
64 3000, 65 3000,
65 4000, 66 4000,
66 5000, 67 5000,
67 7500, 68 7500,
68 10000, 69 10000,
69 15000, 70 15000,
70 20000 71 20000
71 }; 72 };
72 73
73 static int kTabLoadStatsAutoCleanupTimeoutSeconds = 30; 74 static int kTabLoadStatsAutoCleanupTimeoutSeconds = 30;
74 75
76 const char* kRequestStatusNames[] = {
77 "CacheWait",
78 "NetworkWait",
79 "Active",
80 "None",
81 "Max"
82 };
83
84 COMPILE_ASSERT(arraysize(kRequestStatusNames) ==
85 chrome_browser_net::LoadTimeStats::REQUEST_STATUS_MAX + 1,
86 LoadTimeStats_RequestStatus_names_mismatch);
87
88 const char* kHistogramTypeNames[] = {
89 "FinalAggregate",
90 "FinalCumulativePercentage",
91 "IntermediateAggregate",
92 "IntermediateCumulativePercentage",
93 "Max"
94 };
95
96 COMPILE_ASSERT(arraysize(kHistogramTypeNames) ==
97 chrome_browser_net::LoadTimeStats::HISTOGRAM_MAX + 1,
98 LoadTimeStats_HistogramType_names_mismatch);
99
75 } // namespace 100 } // namespace
76 101
77 namespace chrome_browser_net { 102 namespace chrome_browser_net {
78 103
79 // Helper struct keeping stats about the page load progress & cache usage 104 // Helper struct keeping stats about the page load progress & cache usage
80 // stats during the pageload so far for a given RenderView, identified 105 // stats during the pageload so far for a given RenderView, identified
81 // by a pair of process id and route id. 106 // by a pair of process id and route id.
82 struct CacheStats::TabLoadStats { 107 class LoadTimeStats::TabLoadStats {
83 TabLoadStats(std::pair<int, int> render_view_id, CacheStats* owner) 108 public:
84 : render_view_id(render_view_id), 109 // Stores the time taken by all requests while they have a certain
85 num_active(0), 110 // RequestStatus.
86 spinner_started(false), 111 class PerStatusStats {
87 next_timer_index(0), 112 public:
88 timer(false, false) { 113 PerStatusStats() : num_active_(0) {
114 }
115
116 void UpdateTotalTimes() {
117 DCHECK_GE(num_active_, 0);
118 base::TimeTicks now = base::TimeTicks::Now();
119 if (num_active_ > 0) {
120 total_time_ += now - last_update_time_;
121 total_cumulative_time_ +=
122 (now - last_update_time_) * static_cast<int64>(num_active_);
123 }
124 last_update_time_ = now;
125 }
126
127 void ResetTimes() {
128 last_update_time_ = base::TimeTicks::Now();
129 total_time_ = base::TimeDelta();
130 total_cumulative_time_ = base::TimeDelta();
131 }
132
133 void IncrementNumActive() {
134 num_active_++;
135 }
136
137 void DecrementNumActiveIfPositive() {
138 if (num_active_ > 0)
139 num_active_--;
140 }
141
142 int num_active() { return num_active_; }
143 void set_num_active(int num_active) { num_active_ = num_active; }
144 base::TimeDelta total_time() { return total_time_; }
145 base::TimeDelta total_cumulative_time() { return total_cumulative_time_; }
146
147 private:
148 int num_active_;
149 base::TimeTicks last_update_time_;
150 base::TimeDelta total_time_;
151 base::TimeDelta total_cumulative_time_;
152 };
153
154 TabLoadStats(std::pair<int, int> render_view_id, LoadTimeStats* owner)
155 : render_view_id_(render_view_id),
156 spinner_started_(false),
157 next_timer_index_(0),
158 timer_(false, false) {
89 // Initialize the timer to do an automatic cleanup. If a pageload is 159 // Initialize the timer to do an automatic cleanup. If a pageload is
90 // started for the TabLoadStats within that timeframe, CacheStats 160 // started for the TabLoadStats within that timeframe, LoadTimeStats
91 // will start using the timer, thereby cancelling the cleanup. 161 // will start using the timer, thereby cancelling the cleanup.
92 // Once CacheStats starts the timer, the object is guaranteed to be 162 // Once LoadTimeStats starts the timer, the object is guaranteed to be
93 // destroyed eventually, so there is no more need for automatic cleanup at 163 // destroyed eventually, so there is no more need for automatic cleanup at
94 // that point. 164 // that point.
95 timer.Start(FROM_HERE, 165 timer_.Start(FROM_HERE,
96 base::TimeDelta::FromSeconds( 166 base::TimeDelta::FromSeconds(
97 kTabLoadStatsAutoCleanupTimeoutSeconds), 167 kTabLoadStatsAutoCleanupTimeoutSeconds),
98 base::Bind(&CacheStats::RemoveTabLoadStats, 168 base::Bind(&LoadTimeStats::RemoveTabLoadStats,
99 base::Unretained(owner), 169 base::Unretained(owner),
100 render_view_id)); 170 render_view_id_));
101 } 171 }
102 172
103 std::pair<int, int> render_view_id; 173 typedef std::pair<int, int> RenderViewId;
104 int num_active; 174 typedef PerStatusStats PerStatusStatsArray[REQUEST_STATUS_MAX];
105 bool spinner_started; 175 typedef base::hash_map<const net::URLRequest*, RequestStatus> RequestMap;
106 base::TimeTicks load_start_time; 176
107 base::TimeTicks cache_start_time; 177 RenderViewId& render_view_id() { return render_view_id_; }
108 base::TimeDelta cache_total_time; 178 PerStatusStatsArray& per_status_stats() { return per_status_stats_; }
109 int next_timer_index; 179 bool spinner_started() { return spinner_started_; }
110 base::Timer timer; 180 void set_spinner_started(bool value) { spinner_started_ = value; }
111 // URLRequest's for which there are outstanding cache transactions. 181 base::TimeTicks load_start_time() { return load_start_time_; }
112 base::hash_set<const net::URLRequest*> active_requests; 182 int next_timer_index() { return next_timer_index_; }
183 void set_next_timer_index(int index) { next_timer_index_ = index; }
184 base::Timer& timer() { return timer_; }
185 RequestMap& active_requests() { return active_requests_; }
186
187 private:
188 RenderViewId render_view_id_;
189 PerStatusStatsArray per_status_stats_;
190 bool spinner_started_;
191 base::TimeTicks load_start_time_;
192 int next_timer_index_;
193 base::Timer timer_;
194 // Currently active URLRequests.
195 RequestMap active_requests_;
113 }; 196 };
114 197
115 CacheStatsTabHelper::CacheStatsTabHelper(TabContents* tab) 198 LoadTimeStatsTabHelper::LoadTimeStatsTabHelper(TabContents* tab)
116 : content::WebContentsObserver(tab->web_contents()), 199 : content::WebContentsObserver(tab->web_contents()) {
117 cache_stats_(NULL) {
118 is_otr_profile_ = tab->profile()->IsOffTheRecord(); 200 is_otr_profile_ = tab->profile()->IsOffTheRecord();
119 } 201 }
120 202
121 CacheStatsTabHelper::~CacheStatsTabHelper() { 203 LoadTimeStatsTabHelper::~LoadTimeStatsTabHelper() {
122 } 204 }
123 205
124 void CacheStatsTabHelper::DidStartProvisionalLoadForFrame( 206 void LoadTimeStatsTabHelper::DidStartProvisionalLoadForFrame(
125 int64 frame_id, 207 int64 frame_id,
126 bool is_main_frame, 208 bool is_main_frame,
127 const GURL& validated_url, 209 const GURL& validated_url,
128 bool is_error_page, 210 bool is_error_page,
129 content::RenderViewHost* render_view_host) { 211 content::RenderViewHost* render_view_host) {
130 if (!is_main_frame) 212 if (!is_main_frame)
131 return; 213 return;
132 if (!validated_url.SchemeIs("http")) 214 if (!validated_url.SchemeIs("http"))
133 return; 215 return;
134 NotifyCacheStats(CacheStats::SPINNER_START, render_view_host); 216 NotifyLoadTimeStats(LoadTimeStats::SPINNER_START, render_view_host);
135 } 217 }
136 218
137 void CacheStatsTabHelper::DidStopLoading(RenderViewHost* render_view_host) { 219 void LoadTimeStatsTabHelper::DidStopLoading(RenderViewHost* render_view_host) {
138 NotifyCacheStats(CacheStats::SPINNER_STOP, render_view_host); 220 NotifyLoadTimeStats(LoadTimeStats::SPINNER_STOP, render_view_host);
139 } 221 }
140 222
141 void CacheStatsTabHelper::NotifyCacheStats( 223 void LoadTimeStatsTabHelper::NotifyLoadTimeStats(
142 CacheStats::TabEvent event, 224 LoadTimeStats::TabEvent event,
143 RenderViewHost* render_view_host) { 225 RenderViewHost* render_view_host) {
144 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 226 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
145 if (is_otr_profile_) 227 if (is_otr_profile_)
146 return; 228 return;
147 int process_id = render_view_host->GetProcess()->GetID(); 229 int process_id = render_view_host->GetProcess()->GetID();
148 int route_id = render_view_host->GetRoutingID(); 230 int route_id = render_view_host->GetRoutingID();
149 BrowserThread::PostTask( 231 BrowserThread::PostTask(
150 BrowserThread::IO, FROM_HERE, 232 BrowserThread::IO, FROM_HERE,
151 base::Bind(&CallCacheStatsTabEventOnIOThread, 233 base::Bind(&CallLoadTimeStatsTabEventOnIOThread,
152 std::pair<int, int>(process_id, route_id), 234 std::pair<int, int>(process_id, route_id),
153 event, 235 event,
154 base::Unretained(g_browser_process->io_thread()))); 236 base::Unretained(g_browser_process->io_thread())));
155 } 237 }
156 238
157 CacheStats::CacheStats() { 239 LoadTimeStats::LoadTimeStats() {
158 for (int i = 0; 240 for (int status = REQUEST_STATUS_CACHE_WAIT;
159 i < static_cast<int>(arraysize(kStatsCollectionTimesMs)); 241 status <= REQUEST_STATUS_ACTIVE;
160 i++) { 242 status++) {
161 final_histograms_.push_back( 243 for (int histogram_type = HISTOGRAM_FINAL_AGGREGATE;
162 base::LinearHistogram::FactoryGet( 244 histogram_type < HISTOGRAM_MAX;
163 "CacheStats.FractionCacheUseFinalPLT_" + 245 histogram_type++) {
164 base::IntToString(kStatsCollectionTimesMs[i]), 246 for (int i = 0;
165 0, 101, 102, base::Histogram::kUmaTargetedHistogramFlag)); 247 i < static_cast<int>(arraysize(kStatsCollectionTimesMs));
166 intermediate_histograms_.push_back( 248 i++) {
167 base::LinearHistogram::FactoryGet( 249 string histogram_name = string("LoadTimeStats.Fraction_") +
168 "CacheStats.FractionCacheUseIntermediatePLT_" + 250 string(kRequestStatusNames[status]) + string("_") +
169 base::IntToString(kStatsCollectionTimesMs[i]), 251 string(kHistogramTypeNames[histogram_type]) + string("_") +
170 0, 101, 102, base::Histogram::kUmaTargetedHistogramFlag)); 252 base::IntToString(kStatsCollectionTimesMs[i]);
253 histograms_[status][histogram_type].push_back(
254 base::LinearHistogram::FactoryGet(
255 histogram_name,
256 0, 101, 102, base::Histogram::kUmaTargetedHistogramFlag));
257 }
258 DCHECK_EQ(histograms_[status][histogram_type].size(),
259 arraysize(kStatsCollectionTimesMs));
260 }
171 } 261 }
172 DCHECK_EQ(final_histograms_.size(), arraysize(kStatsCollectionTimesMs));
173 DCHECK_EQ(intermediate_histograms_.size(),
174 arraysize(kStatsCollectionTimesMs));
175 } 262 }
176 263
177 CacheStats::~CacheStats() { 264 LoadTimeStats::~LoadTimeStats() {
178 STLDeleteValues(&tab_load_stats_); 265 STLDeleteValues(&tab_load_stats_);
179 } 266 }
180 267
181 CacheStats::TabLoadStats* CacheStats::GetTabLoadStats( 268 LoadTimeStats::TabLoadStats* LoadTimeStats::GetTabLoadStats(
182 std::pair<int, int> render_view_id) { 269 std::pair<int, int> render_view_id) {
183 TabLoadStatsMap::const_iterator it = tab_load_stats_.find(render_view_id); 270 TabLoadStatsMap::const_iterator it = tab_load_stats_.find(render_view_id);
184 if (it != tab_load_stats_.end()) 271 if (it != tab_load_stats_.end())
185 return it->second; 272 return it->second;
186 TabLoadStats* new_tab_load_stats = new TabLoadStats(render_view_id, this); 273 TabLoadStats* new_tab_load_stats = new TabLoadStats(render_view_id, this);
187 tab_load_stats_[render_view_id] = new_tab_load_stats; 274 tab_load_stats_[render_view_id] = new_tab_load_stats;
188 return new_tab_load_stats; 275 return new_tab_load_stats;
189 } 276 }
190 277
191 void CacheStats::RemoveTabLoadStats(std::pair<int, int> render_view_id) { 278 void LoadTimeStats::RemoveTabLoadStats(std::pair<int, int> render_view_id) {
192 TabLoadStatsMap::iterator it = tab_load_stats_.find(render_view_id); 279 TabLoadStatsMap::iterator it = tab_load_stats_.find(render_view_id);
193 if (it != tab_load_stats_.end()) { 280 if (it != tab_load_stats_.end()) {
194 delete it->second; 281 delete it->second;
195 tab_load_stats_.erase(it); 282 tab_load_stats_.erase(it);
196 } 283 }
197 } 284 }
198 285
199 void CacheStats::OnCacheWaitStateChange( 286 void LoadTimeStats::OnRequestWaitStateChange(
200 const net::URLRequest& request, 287 const net::URLRequest& request,
201 net::NetworkDelegate::CacheWaitState state) { 288 net::NetworkDelegate::RequestWaitState state) {
202 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 289 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
203 if (main_request_contexts_.count(request.context()) < 1) 290 if (main_request_contexts_.count(request.context()) < 1)
204 return; 291 return;
205 int process_id, route_id; 292 int process_id, route_id;
206 if (!GetRenderView(request, &process_id, &route_id)) 293 if (!GetRenderView(request, &process_id, &route_id))
207 return; 294 return;
208 TabLoadStats* stats = 295 TabLoadStats* stats =
209 GetTabLoadStats(std::pair<int, int>(process_id, route_id)); 296 GetTabLoadStats(std::pair<int, int>(process_id, route_id));
210 bool newly_started = false; 297 RequestStatus old_status = REQUEST_STATUS_NONE;
211 bool newly_finished = false; 298 if (stats->active_requests().count(&request) > 0)
299 old_status = stats->active_requests()[&request];
300 RequestStatus new_status = REQUEST_STATUS_NONE;
212 switch (state) { 301 switch (state) {
213 case net::NetworkDelegate::CACHE_WAIT_STATE_START: 302 case net::NetworkDelegate::REQUEST_WAIT_STATE_CACHE_START:
214 DCHECK(stats->active_requests.count(&request) == 0); 303 DCHECK(old_status == REQUEST_STATUS_NONE ||
215 newly_started = true; 304 old_status == REQUEST_STATUS_ACTIVE);
216 stats->active_requests.insert(&request); 305 new_status = REQUEST_STATUS_CACHE_WAIT;
217 break; 306 break;
218 case net::NetworkDelegate::CACHE_WAIT_STATE_FINISH: 307 case net::NetworkDelegate::REQUEST_WAIT_STATE_CACHE_FINISH:
219 if (stats->active_requests.count(&request) > 0) { 308 DCHECK(old_status == REQUEST_STATUS_NONE ||
220 stats->active_requests.erase(&request); 309 old_status == REQUEST_STATUS_CACHE_WAIT);
221 newly_finished = true; 310 new_status = REQUEST_STATUS_ACTIVE;
222 }
223 break; 311 break;
224 case net::NetworkDelegate::CACHE_WAIT_STATE_RESET: 312 case net::NetworkDelegate::REQUEST_WAIT_STATE_NETWORK_START:
225 if (stats->active_requests.count(&request) > 0) { 313 DCHECK(old_status == REQUEST_STATUS_NONE ||
226 stats->active_requests.erase(&request); 314 old_status == REQUEST_STATUS_ACTIVE);
227 newly_finished = true; 315 new_status = REQUEST_STATUS_NETWORK_WAIT;
228 } 316 break;
317 case net::NetworkDelegate::REQUEST_WAIT_STATE_NETWORK_FINISH:
318 DCHECK(old_status == REQUEST_STATUS_NONE ||
319 old_status == REQUEST_STATUS_NETWORK_WAIT);
320 new_status = REQUEST_STATUS_ACTIVE;
321 break;
322 case net::NetworkDelegate::REQUEST_WAIT_STATE_RESET:
323 new_status = REQUEST_STATUS_NONE;
229 break; 324 break;
230 } 325 }
231 DCHECK_GE(stats->num_active, 0); 326 if (old_status == new_status)
232 if (newly_started) { 327 return;
233 DCHECK(!newly_finished); 328 if (old_status != REQUEST_STATUS_NONE) {
234 if (stats->num_active == 0) { 329 TabLoadStats::PerStatusStats* status_stats =
235 stats->cache_start_time = base::TimeTicks::Now(); 330 &(stats->per_status_stats()[old_status]);
236 } 331 DCHECK_GE(status_stats->num_active(), 0);
237 stats->num_active++; 332 status_stats->UpdateTotalTimes();
333 status_stats->DecrementNumActiveIfPositive();
334 DCHECK_GE(status_stats->num_active(), 0);
238 } 335 }
239 if (newly_finished) { 336 if (new_status != REQUEST_STATUS_NONE) {
240 DCHECK(!newly_started); 337 TabLoadStats::PerStatusStats* status_stats =
241 if (stats->num_active == 1) { 338 &(stats->per_status_stats()[new_status]);
242 stats->cache_total_time += 339 DCHECK_GE(status_stats->num_active(), 0);
243 base::TimeTicks::Now() - stats->cache_start_time; 340 status_stats->UpdateTotalTimes();
244 } 341 status_stats->IncrementNumActive();
245 stats->num_active--; 342 DCHECK_GE(status_stats->num_active(), 0);
343 stats->active_requests()[&request] = new_status;
344 } else {
345 stats->active_requests().erase(&request);
246 } 346 }
247 DCHECK_GE(stats->num_active, 0);
248 } 347 }
249 348
250 void CacheStats::OnTabEvent(std::pair<int, int> render_view_id, 349 void LoadTimeStats::OnTabEvent(std::pair<int, int> render_view_id,
251 TabEvent event) { 350 TabEvent event) {
252 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 351 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
253 TabLoadStats* stats = GetTabLoadStats(render_view_id); 352 TabLoadStats* stats = GetTabLoadStats(render_view_id);
254 if (event == SPINNER_START) { 353 if (event == SPINNER_START) {
255 stats->spinner_started = true; 354 stats->set_spinner_started(true);
256 stats->cache_total_time = base::TimeDelta(); 355 for (int status = REQUEST_STATUS_CACHE_WAIT;
257 stats->cache_start_time = base::TimeTicks::Now(); 356 status <= REQUEST_STATUS_ACTIVE; status++) {
258 stats->load_start_time = base::TimeTicks::Now(); 357 stats->per_status_stats()[status].ResetTimes();
259 stats->next_timer_index = 0; 358 }
359 stats->set_next_timer_index(0);
260 ScheduleTimer(stats); 360 ScheduleTimer(stats);
261 } else { 361 } else {
262 DCHECK_EQ(event, SPINNER_STOP); 362 DCHECK_EQ(event, SPINNER_STOP);
263 if (stats->spinner_started) { 363 if (stats->spinner_started()) {
264 stats->spinner_started = false; 364 stats->set_spinner_started(false);
265 base::TimeDelta load_time = 365 base::TimeDelta load_time =
266 base::TimeTicks::Now() - stats->load_start_time; 366 base::TimeTicks::Now() - stats->load_start_time();
267 if (stats->num_active > 1) 367 RecordHistograms(load_time, stats, true);
268 stats->cache_total_time +=
269 base::TimeTicks::Now() - stats->cache_start_time;
270 RecordCacheFractionHistogram(load_time, stats->cache_total_time, true,
271 stats->next_timer_index);
272 } 368 }
273 RemoveTabLoadStats(render_view_id); 369 RemoveTabLoadStats(render_view_id);
274 } 370 }
275 } 371 }
276 372
277 void CacheStats::ScheduleTimer(TabLoadStats* stats) { 373 void LoadTimeStats::ScheduleTimer(TabLoadStats* stats) {
278 int timer_index = stats->next_timer_index; 374 int timer_index = stats->next_timer_index();
279 DCHECK(timer_index >= 0 && 375 DCHECK(timer_index >= 0 &&
280 timer_index < static_cast<int>(arraysize(kStatsCollectionTimesMs))); 376 timer_index < static_cast<int>(arraysize(kStatsCollectionTimesMs)));
281 base::TimeDelta delta = 377 base::TimeDelta delta =
282 base::TimeDelta::FromMilliseconds(kStatsCollectionTimesMs[timer_index]); 378 base::TimeDelta::FromMilliseconds(kStatsCollectionTimesMs[timer_index]);
283 delta -= base::TimeTicks::Now() - stats->load_start_time; 379 delta -= base::TimeTicks::Now() - stats->load_start_time();
284 380
285 // If the ScheduleTimer call was delayed significantly, like when one's using 381 // If the ScheduleTimer call was delayed significantly, like when one's using
286 // a debugger, don't try to start the timer with a negative time. 382 // a debugger, don't try to start the timer with a negative time.
287 if (delta < base::TimeDelta()) { 383 if (delta < base::TimeDelta()) {
288 RemoveTabLoadStats(stats->render_view_id); 384 RemoveTabLoadStats(stats->render_view_id());
289 return; 385 return;
290 } 386 }
291 387
292 stats->timer.Start(FROM_HERE, 388 stats->timer().Start(FROM_HERE,
293 delta, 389 delta,
294 base::Bind(&CacheStats::TimerCallback, 390 base::Bind(&LoadTimeStats::TimerCallback,
295 base::Unretained(this), 391 base::Unretained(this),
296 base::Unretained(stats))); 392 base::Unretained(stats)));
297 } 393 }
298 394
299 void CacheStats::TimerCallback(TabLoadStats* stats) { 395 void LoadTimeStats::TimerCallback(TabLoadStats* stats) {
300 DCHECK(stats->spinner_started); 396 DCHECK(stats->spinner_started());
301 base::TimeDelta load_time = base::TimeTicks::Now() - stats->load_start_time; 397 base::TimeDelta load_time = base::TimeTicks::Now() - stats->load_start_time();
302 base::TimeDelta cache_time = stats->cache_total_time; 398 RecordHistograms(load_time, stats, false);
303 if (stats->num_active > 1) 399 stats->set_next_timer_index(stats->next_timer_index() + 1);
304 cache_time += base::TimeTicks::Now() - stats->cache_start_time; 400 if (stats->next_timer_index() <
305 RecordCacheFractionHistogram(load_time, cache_time, false,
306 stats->next_timer_index);
307 stats->next_timer_index++;
308 if (stats->next_timer_index <
309 static_cast<int>(arraysize(kStatsCollectionTimesMs))) { 401 static_cast<int>(arraysize(kStatsCollectionTimesMs))) {
310 ScheduleTimer(stats); 402 ScheduleTimer(stats);
311 } else { 403 } else {
312 RemoveTabLoadStats(stats->render_view_id); 404 RemoveTabLoadStats(stats->render_view_id());
313 } 405 }
314 } 406 }
315 407
316 void CacheStats::RecordCacheFractionHistogram(base::TimeDelta elapsed, 408 void LoadTimeStats::RecordHistograms(base::TimeDelta elapsed,
317 base::TimeDelta cache_time, 409 TabLoadStats* stats,
318 bool is_load_done, 410 bool is_load_done) {
319 int timer_index) { 411 int timer_index = stats->next_timer_index();
320 DCHECK(timer_index >= 0 && 412 DCHECK(timer_index >= 0 &&
321 timer_index < static_cast<int>(arraysize(kStatsCollectionTimesMs))); 413 timer_index < static_cast<int>(arraysize(kStatsCollectionTimesMs)));
322 414
323 if (elapsed.InMilliseconds() <= 0) 415 if (elapsed.InMilliseconds() <= 0)
324 return; 416 return;
325 417
326 int64 cache_fraction_percentage = 418 base::TimeDelta total_cumulative;
327 100 * cache_time.InMilliseconds() / elapsed.InMilliseconds(); 419 for (int status = REQUEST_STATUS_CACHE_WAIT;
420 status <= REQUEST_STATUS_ACTIVE;
421 status++) {
422 total_cumulative +=
423 stats->per_status_stats()[status].total_cumulative_time();
424 }
328 425
329 DCHECK(cache_fraction_percentage >= 0 && cache_fraction_percentage <= 100); 426 for (int status = REQUEST_STATUS_CACHE_WAIT;
427 status <= REQUEST_STATUS_ACTIVE;
428 status++) {
429 TabLoadStats::PerStatusStats* status_stats =
430 &(stats->per_status_stats()[status]);
330 431
331 if (is_load_done) { 432 int64 fraction_percentage = 100 *
332 final_histograms_[timer_index]->Add(cache_fraction_percentage); 433 status_stats->total_time().InMilliseconds() / elapsed.InMilliseconds();
333 } else { 434 DCHECK(fraction_percentage >= 0 && fraction_percentage <= 100);
334 intermediate_histograms_[timer_index]->Add(cache_fraction_percentage); 435 if (is_load_done) {
436 histograms_[status][HISTOGRAM_FINAL_AGGREGATE][timer_index]->Add(
437 fraction_percentage);
438 } else {
439 histograms_[status][HISTOGRAM_INTERMEDIATE_AGGREGATE][timer_index]->Add(
440 fraction_percentage);
441 }
442
443 if (total_cumulative.InMilliseconds() > 0) {
444 fraction_percentage = 100 *
445 status_stats->total_cumulative_time().InMilliseconds() /
446 total_cumulative.InMilliseconds();
447 DCHECK(fraction_percentage >= 0 && fraction_percentage <= 100);
448 if (is_load_done) {
449 histograms_[status][HISTOGRAM_FINAL_CUMULATIVE_PERCENTAGE]
450 [timer_index]->Add(fraction_percentage);
451 } else {
452 histograms_[status][HISTOGRAM_INTERMEDIATE_CUMULATIVE_PERCENTAGE]
453 [timer_index]->Add(fraction_percentage);
454 }
455 }
335 } 456 }
336 } 457 }
337 458
338 void CacheStats::RegisterURLRequestContext( 459 void LoadTimeStats::RegisterURLRequestContext(
339 const net::URLRequestContext* context, 460 const net::URLRequestContext* context,
340 ChromeURLRequestContext::ContextType type) { 461 ChromeURLRequestContext::ContextType type) {
341 if (type == ChromeURLRequestContext::CONTEXT_TYPE_MAIN) 462 if (type == ChromeURLRequestContext::CONTEXT_TYPE_MAIN)
342 main_request_contexts_.insert(context); 463 main_request_contexts_.insert(context);
343 } 464 }
344 465
345 void CacheStats::UnregisterURLRequestContext( 466 void LoadTimeStats::UnregisterURLRequestContext(
346 const net::URLRequestContext* context) { 467 const net::URLRequestContext* context) {
347 main_request_contexts_.erase(context); 468 main_request_contexts_.erase(context);
348 } 469 }
349 470
350 } // namespace chrome_browser_net 471 } // namespace chrome_browser_net
OLDNEW
« no previous file with comments | « chrome/browser/net/load_time_stats.h ('k') | chrome/browser/profiles/off_the_record_profile_io_data.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698