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

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

Issue 10736066: Adding histograms showing fraction of page load times (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 5 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "chrome/browser/net/cache_stats.h"
6
7 #include <vector>
8
9 #include "base/hash_tables.h"
10 #include "base/metrics/histogram.h"
11 #include "base/stl_util.h"
12 #include "base/string_number_conversions.h"
13 #include "base/timer.h"
14 #include "chrome/browser/ui/tab_contents/tab_contents.h"
15 #include "content/public/browser/browser_thread.h"
16 #include "content/public/browser/render_process_host.h"
17 #include "content/public/browser/render_view_host.h"
18 #include "content/public/browser/resource_request_info.h"
19 #include "content/public/browser/web_contents.h"
20 #include "net/url_request/url_request.h"
21 #include <stdio.h>
22
23 using content::BrowserThread;
24 using content::ResourceRequestInfo;
25
26 #if defined(COMPILER_GCC)
27
28 namespace BASE_HASH_NAMESPACE {
29 template <>
30 struct hash<const net::URLRequest*> {
31 std::size_t operator()(const net::URLRequest* value) const {
32 return reinterpret_cast<std::size_t>(value);
33 }
34 };
35 }
36
37 #endif
38
39 namespace chrome_browser_net {
40
41 namespace {
42
43 bool GetRenderView(const net::URLRequest& request,
44 int* process_id, int* route_id) {
45 const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(&request);
46 if (!info)
47 return false;
48
49 return info->GetAssociatedRenderView(process_id, route_id);
50 }
51
52 // Times after a load has started at which stats are collected.
53 const int kStatsCollectionTimesMs[] = {
54 500,
55 1000,
56 2000,
57 3000,
58 4000,
59 5000,
60 7500,
61 10000,
62 15000,
63 20000
64 };
65
66 } // namespace
67
68 // static
69 CacheStats* CacheStats::GetInstance() {
70 return Singleton<CacheStats>::get();
71 }
72
73 struct CacheStats::TabLoadStats {
74 int num_active_;
75 base::TimeTicks load_start_time_;
76 base::TimeTicks cache_start_time_;
77 base::TimeDelta cache_total_time_;
78 base::Timer timer_;
79 typedef base::hash_map<const net::URLRequest*, int> PerRequestNumActiveMap;
80 PerRequestNumActiveMap per_request_num_active_;
81 TabLoadStats()
82 : num_active_(0),
83 timer_(false, false) {
84 }
85 };
86
87 CacheStatsTabHelper::CacheStatsTabHelper(TabContents* tab)
88 : content::WebContentsObserver(tab->web_contents()),
89 cache_stats_(CacheStats::GetInstance()),
90 is_loading_(false),
91 render_view_id_initialized_(false) {
92 }
93
94 CacheStatsTabHelper::~CacheStatsTabHelper() {
95 DidStopLoading();
96 }
97
98 void CacheStatsTabHelper::DidStartProvisionalLoadForFrame(
99 int64 frame_id,
100 bool is_main_frame,
101 const GURL& validated_url,
102 bool is_error_page,
103 content::RenderViewHost* render_view_host) {
104 if (!render_view_id_initialized_)
mmenke 2012/07/19 16:12:54 Can this happen?
tburkard 2012/07/19 16:36:15 I don't think it can, but I wanted to consider thi
105 return;
106 if (!is_main_frame)
107 return;
108 if (!validated_url.SchemeIs("http"))
109 return;
110 if (is_loading_)
mmenke 2012/07/19 16:12:54 This check worries me a bit, in terms of getting a
tburkard 2012/07/19 16:36:15 Fixed. On 2012/07/19 16:12:54, Matt Menke wrote:
111 return;
112 is_loading_ = true;
113 NotifyCacheStats(true);
114 }
115
116 void CacheStatsTabHelper::DidStopLoading() {
117 if (!is_loading_)
118 return;
119 is_loading_ = false;
120 NotifyCacheStats(false);
121 }
122
123 void CacheStatsTabHelper::RenderViewCreated(
124 content::RenderViewHost* render_view_host) {
125 DidStopLoading();
126 int process_id = render_view_host->GetProcess()->GetID();
127 int route_id = render_view_host->GetRoutingID();
128 render_view_id_ = std::pair<int, int>(process_id, route_id);
129 render_view_id_initialized_ = true;
130 }
131
132 void CacheStatsTabHelper::NotifyCacheStats(bool loading) {
133 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
134 BrowserThread::PostTask(
135 BrowserThread::IO, FROM_HERE,
136 base::Bind(&CacheStats::OnTabSpinnerChange,
137 base::Unretained(cache_stats_),
138 render_view_id_, loading));
139 }
140
141 CacheStats::CacheStats() :
142 registered_message_loop_destruction_observer_(false) {
143 for (int i = 0;
144 i < static_cast<int>(arraysize(kStatsCollectionTimesMs));
145 i++) {
146 final_histograms_.push_back(
147 base::LinearHistogram::FactoryGet(
148 "DiskCache.FractionCacheUseFinalPLT_" +
149 base::IntToString(kStatsCollectionTimesMs[i]),
150 0, 101, 102, base::Histogram::kUmaTargetedHistogramFlag));
151 intermediate_histograms_.push_back(
152 base::LinearHistogram::FactoryGet(
153 "DiskCache.FractionCacheUseIntermediatePLT_" +
154 base::IntToString(kStatsCollectionTimesMs[i]),
155 0, 101, 102, base::Histogram::kNoFlags));
156 }
157 DCHECK(final_histograms_.size() == arraysize(kStatsCollectionTimesMs));
158 DCHECK(intermediate_histograms_.size() == arraysize(kStatsCollectionTimesMs));
159 }
160
161 CacheStats::~CacheStats() {
162 }
163
164 void CacheStats::WillDestroyCurrentMessageLoop() {
165 MessageLoop::current()->RemoveDestructionObserver(this);
166 STLDeleteValues(&tab_load_stats_);
167 registered_message_loop_destruction_observer_ = false;
168 }
169
170 CacheStats::TabLoadStats* CacheStats::GetTabLoadStats(
171 std::pair<int, int> render_view_id) {
172 if (!registered_message_loop_destruction_observer_) {
173 MessageLoop::current()->AddDestructionObserver(this);
174 registered_message_loop_destruction_observer_ = true;
175 }
176 if (tab_load_stats_.count(render_view_id) < 1)
177 tab_load_stats_[render_view_id] = new TabLoadStats();
178 return tab_load_stats_[render_view_id];
179 }
180
181 void CacheStats::OnCacheWaitStateChange(
182 const net::URLRequest& request,
183 net::NetworkDelegate::CacheWaitState state) {
184 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
185 int render_view, route_id;
186 if (!GetRenderView(request, &render_view, &route_id))
187 return;
188 TabLoadStats* stats =
189 GetTabLoadStats(std::pair<int, int>(render_view, route_id));
190 bool newly_started = false;
191 bool newly_finished = false;
192 std::pair<TabLoadStats::PerRequestNumActiveMap::iterator, bool> insert_ret =
193 stats->per_request_num_active_.insert(
194 std::pair<const net::URLRequest*, int>(&request, 0));
195 TabLoadStats::PerRequestNumActiveMap::iterator entry = insert_ret.first;
196 DCHECK(entry->second >= 0);
197 switch (state) {
198 case net::NetworkDelegate::CACHE_WAIT_STATE_START:
199 if (entry->second == 0)
200 newly_started = true;
201 entry->second++;
202 break;
203 case net::NetworkDelegate::CACHE_WAIT_STATE_FINISH:
204 if (entry->second > 0) {
205 entry->second--;
206 if (entry->second == 0)
207 newly_finished = true;
208 }
209 break;
210 case net::NetworkDelegate::CACHE_WAIT_STATE_DONE:
211 if (entry->second > 0) {
212 entry->second = 0;
213 newly_finished = true;
214 }
215 break;
216 }
217 DCHECK(entry->second >= 0);
218 DCHECK(!newly_started || !newly_finished);
219 if (newly_started) {
220 if (stats->num_active_ == 0) {
221 stats->cache_start_time_ = base::TimeTicks::Now();
222 }
223 stats->num_active_++;
224 }
225 if (newly_finished) {
226 if (stats->num_active_ == 1) {
227 stats->cache_total_time_ +=
228 base::TimeTicks::Now() - stats->cache_start_time_;
229 }
230 stats->num_active_--;
231 }
232 }
233
234 void CacheStats::OnTabSpinnerChange(std::pair<int, int> render_view_id,
235 bool loading) {
236 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
237 TabLoadStats* stats = GetTabLoadStats(render_view_id);
238 if (loading) {
239 stats->cache_total_time_ = base::TimeDelta();
240 stats->cache_start_time_ = base::TimeTicks::Now();
241 stats->load_start_time_ = base::TimeTicks::Now();
242 ScheduleTimer(stats, 0);
243 } else {
244 stats->timer_.Stop();
245 base::TimeDelta load_time =
246 base::TimeTicks::Now() - stats->load_start_time_;
247 if (stats->num_active_ > 1)
248 stats->cache_total_time_ +=
249 base::TimeTicks::Now() - stats->cache_start_time_;
250 RecordCacheFractionHistogram(load_time, stats->cache_total_time_, true);
251 }
252 }
253
254 void CacheStats::ScheduleTimer(TabLoadStats* stats, int timer_index) {
255 DCHECK(timer_index >= 0 &&
256 timer_index < static_cast<int>(arraysize(kStatsCollectionTimesMs)));
257 base::TimeDelta delta =
258 base::TimeDelta::FromMilliseconds(kStatsCollectionTimesMs[timer_index]);
259 delta -= base::TimeTicks::Now() - stats->load_start_time_;
260 stats->timer_.Start(FROM_HERE,
261 delta,
262 base::Bind(&CacheStats::TimerCb,
263 base::Unretained(this),
264 base::Unretained(stats),
265 timer_index));
266 }
267
268 void CacheStats::TimerCb(TabLoadStats* stats, int timer_index) {
269 base::TimeDelta load_time = base::TimeTicks::Now() - stats->load_start_time_;
270 base::TimeDelta cache_time = stats->cache_total_time_;
271 if (stats->num_active_ > 1)
272 cache_time += base::TimeTicks::Now() - stats->cache_start_time_;
273 RecordCacheFractionHistogram(load_time, cache_time, false);
274 timer_index++;
275 if (timer_index < static_cast<int>(arraysize(kStatsCollectionTimesMs)))
276 ScheduleTimer(stats, timer_index);
277 }
278
279 void CacheStats::RecordCacheFractionHistogram(base::TimeDelta elapsed,
280 base::TimeDelta cache_time,
281 bool is_load_done) {
282 if (elapsed.InMilliseconds() <= 0)
283 return;
284
285 double cache_fraction =
286 static_cast<double>(cache_time.InMilliseconds()) /
287 static_cast<double>(elapsed.InMilliseconds());
288
289 DCHECK(cache_fraction >= 0.0 && cache_fraction <= 1.0);
290 int cache_fraction_percentage = cache_fraction * 100;
291 DCHECK(cache_fraction_percentage >= 0 && cache_fraction_percentage < 100);
292
293 int index = 0;
294 while (index + 1 < static_cast<int>(arraysize(kStatsCollectionTimesMs)) &&
295 base::TimeDelta::FromMilliseconds(kStatsCollectionTimesMs[index + 1]) <
296 elapsed) {
297 index++;
298 }
299
300 if (is_load_done) {
301 final_histograms_[index]->Add(cache_fraction_percentage);
302 } else {
303 intermediate_histograms_[index]->Add(cache_fraction_percentage);
304 }
305 }
306
307 } // namespace chrome_browser_net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698