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

Side by Side Diff: chrome/browser/sessions/session_restore_stats_collector.cc

Issue 1136523004: [Sessions] Add detailed logging of SessionRestore events. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Refactor and rebase. Created 5 years, 7 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
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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/sessions/session_restore_stats_collector.h" 5 #include "chrome/browser/sessions/session_restore_stats_collector.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "base/metrics/histogram.h" 9 #include "base/metrics/histogram.h"
10 #include "base/strings/stringprintf.h" 10 #include "base/strings/stringprintf.h"
11 #include "content/public/browser/notification_service.h" 11 #include "content/public/browser/notification_service.h"
12 #include "content/public/browser/notification_types.h" 12 #include "content/public/browser/notification_types.h"
13 #include "content/public/browser/render_widget_host_view.h" 13 #include "content/public/browser/render_widget_host_view.h"
14 #include "content/public/browser/web_contents.h" 14 #include "content/public/browser/web_contents.h"
15 15
16 using content::NavigationController; 16 using content::NavigationController;
17 using content::RenderWidgetHost; 17 using content::RenderWidgetHost;
18 using content::WebContents; 18 using content::WebContents;
19 19
20 namespace {
21
22 // Metric names.
23 const char kSessionRestoreActions[] = "SessionRestore.Actions";
24 const char kSessionRestoreTabCount[] = "SessionRestore.TabCount";
25 const char kSessionRestoreTabActions[] = "SessionRestore.TabActions";
26
27 // The enumeration values stored in the kSessionRestoreActions histogram.
28 enum SessionRestoreActionsUma {
29 // Counts the total number of session restores that have occurred.
30 SESSION_RESTORE_ACTIONS_UMA_INITIATED = 0,
31 // Counts the number of session restores that have been deferred tab loadings
32 // for whatever reason (almost certainly due to memory pressure).
33 SESSION_RESTORE_ACTIONS_UMA_DEFERRED_TABS = 1,
34 // The size of this enum. Must be the last entry.
35 SESSION_RESTORE_ACTIONS_UMA_MAX,
36 };
37
38 // The enumeration of values stored in the kSessionRestoreTabActions histogram.
39 enum SessionRestoreTabActionsUma {
40 // Incremented for each tab created in a session restore.
41 SESSION_RESTORE_TAB_ACTIONS_UMA_TAB_CREATED = 0,
42 // Incremented for each tab that session restore decides not to load.
43 SESSION_RESTORE_TAB_ACTIONS_UMA_TAB_LOADING_DEFERRED = 1,
44 // Incremented for each tab that is successfully loaded.
45 SESSION_RESTORE_TAB_ACTIONS_UMA_TAB_LOADED = 2,
46 // Incremented for each session-restore-deferred tab that is subsequently
47 // loaded.
48 SESSION_RESTORE_TAB_ACTIONS_UMA_DEFERRED_TAB_LOADED = 3,
49 // The size of this enum. Must be the last entry.
50 SESSION_RESTORE_TAB_ACTIONS_UMA_MAX,
51 };
52
53 } // namespace
54
20 // static 55 // static
21 void SessionRestoreStatsCollector::TrackTabs( 56 void SessionRestoreStatsCollector::TrackTabs(
22 const std::vector<SessionRestoreDelegate::RestoredTab>& tabs, 57 const std::vector<SessionRestoreDelegate::RestoredTab>& tabs,
23 const base::TimeTicks& restore_started) { 58 const base::TimeTicks& restore_started) {
24 if (!shared_collector_) 59 if (!shared_collector_)
25 shared_collector_ = new SessionRestoreStatsCollector(restore_started); 60 shared_collector_ = new SessionRestoreStatsCollector(restore_started);
26 61
27 shared_collector_->AddTabs(tabs); 62 shared_collector_->AddTabs(tabs);
28 } 63 }
29 64
30 // static 65 // static
31 void SessionRestoreStatsCollector::TrackActiveTabs( 66 void SessionRestoreStatsCollector::DeferTab(
32 const std::vector<SessionRestoreDelegate::RestoredTab>& tabs, 67 content::NavigationController* tab) {
33 const base::TimeTicks& restore_started) { 68 // It only makes sense for this to have been called *after* TrackTabs, so a
34 if (!shared_collector_) 69 // stats collector will always exist.
35 shared_collector_ = new SessionRestoreStatsCollector(restore_started); 70 DCHECK(shared_collector_);
36 71 shared_collector_->DeferTabImpl(tab);
37 std::vector<SessionRestoreDelegate::RestoredTab> active_tabs;
38 for (auto tab : tabs) {
39 if (tab.is_active())
40 active_tabs.push_back(tab);
41 }
42 shared_collector_->AddTabs(active_tabs);
43 } 72 }
44 73
45 SessionRestoreStatsCollector::SessionRestoreStatsCollector( 74 SessionRestoreStatsCollector::SessionRestoreStatsCollector(
46 const base::TimeTicks& restore_started) 75 const base::TimeTicks& restore_started)
47 : got_first_foreground_load_(false), 76 : got_first_foreground_load_(false),
48 got_first_paint_(false), 77 got_first_paint_(false),
49 restore_started_(restore_started), 78 restore_started_(restore_started),
50 tab_count_(0), 79 render_widget_hosts_loading_deferred_count_(0u),
51 max_parallel_tab_loads_(0) { 80 tabs_tracked_deferred_count_(0u),
81 tab_count_(0u),
82 tab_deferred_count_(0u),
83 max_parallel_tab_loads_(0u) {
52 this_retainer_ = this; 84 this_retainer_ = this;
53 registrar_.Add( 85 registrar_.Add(
54 this, content::NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE, 86 this, content::NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE,
55 content::NotificationService::AllSources()); 87 content::NotificationService::AllSources());
56 } 88 }
57 89
58 SessionRestoreStatsCollector::~SessionRestoreStatsCollector() { 90 SessionRestoreStatsCollector::~SessionRestoreStatsCollector() {
59 DCHECK((got_first_paint_ || render_widget_hosts_to_paint_.empty()) && 91 // The collector should only be destroyed when tracking is entirely
60 tabs_tracked_.empty() && render_widget_hosts_loading_.empty()); 92 // finished. It should already have beend detached from being the shared
61 DCHECK(shared_collector_ == this); 93 // collector.
62 shared_collector_ = nullptr; 94 DCHECK(shared_collector_ != this);
95 DCHECK(DoneTracking());
63 } 96 }
64 97
65 void SessionRestoreStatsCollector::Observe( 98 void SessionRestoreStatsCollector::Observe(
66 int type, 99 int type,
67 const content::NotificationSource& source, 100 const content::NotificationSource& source,
68 const content::NotificationDetails& details) { 101 const content::NotificationDetails& details) {
69 switch (type) { 102 switch (type) {
70 case content::NOTIFICATION_LOAD_START: { 103 case content::NOTIFICATION_LOAD_START: {
71 // Add this render_widget_host to the set of those we're waiting for
72 // paints on. We want to only record stats for paints that occur after
73 // a load has finished.
74 NavigationController* tab = 104 NavigationController* tab =
75 content::Source<NavigationController>(source).ptr(); 105 content::Source<NavigationController>(source).ptr();
106 bool is_deferred = IsDeferred(tab);
107
108 // Add this render_widget_host to the set of those that are loading.
76 RenderWidgetHost* render_widget_host = GetRenderWidgetHost(tab); 109 RenderWidgetHost* render_widget_host = GetRenderWidgetHost(tab);
77 DCHECK(render_widget_host); 110 DCHECK(render_widget_host);
78 render_widget_hosts_loading_.insert(render_widget_host); 111 render_widget_hosts_loading_.insert(
112 std::make_pair(render_widget_host, is_deferred));
113 if (is_deferred)
114 ++render_widget_hosts_loading_deferred_count_;
115
79 break; 116 break;
80 } 117 }
81 case content::NOTIFICATION_WEB_CONTENTS_DESTROYED: { 118 case content::NOTIFICATION_WEB_CONTENTS_DESTROYED: {
82 WebContents* web_contents = content::Source<WebContents>(source).ptr(); 119 WebContents* web_contents = content::Source<WebContents>(source).ptr();
83 RemoveTab(&web_contents->GetController()); 120 NavigationController* tab = &web_contents->GetController();
121 RemoveTab(tab);
84 break; 122 break;
85 } 123 }
86 case content::NOTIFICATION_LOAD_STOP: { 124 case content::NOTIFICATION_LOAD_STOP: {
125 // Remove the tab from the tracking maps.
87 NavigationController* tab = 126 NavigationController* tab =
88 content::Source<NavigationController>(source).ptr(); 127 content::Source<NavigationController>(source).ptr();
89 RenderWidgetHost* render_widget_host = GetRenderWidgetHost(tab); 128 RenderWidgetHost* render_widget_host = GetRenderWidgetHost(tab);
90 render_widget_hosts_to_paint_.insert(render_widget_host); 129 auto tab_it = tabs_tracked_.find(tab);
130 bool is_deferred = tab_it->second;
91 RemoveTab(tab); 131 RemoveTab(tab);
132
133 // If first paint hasn't yet been seen then add this tab to the set of
134 // those being tracked for first paints.
135 if (!got_first_paint_ && render_widget_host)
136 render_widget_hosts_to_paint_.insert(render_widget_host);
137
138 // Note the fact that this tab loaded.
139 auto tab_action = is_deferred ?
140 SESSION_RESTORE_TAB_ACTIONS_UMA_DEFERRED_TAB_LOADED :
141 SESSION_RESTORE_TAB_ACTIONS_UMA_TAB_LOADED;
142 UMA_HISTOGRAM_ENUMERATION(kSessionRestoreTabActions,
143 tab_action,
144 SESSION_RESTORE_TAB_ACTIONS_UMA_MAX);
145
146 // Update UMA stats for foreground tabs.
92 if (!got_first_foreground_load_ && render_widget_host && 147 if (!got_first_foreground_load_ && render_widget_host &&
93 render_widget_host->GetView() && 148 render_widget_host->GetView() &&
94 render_widget_host->GetView()->IsShowing()) { 149 render_widget_host->GetView()->IsShowing()) {
95 got_first_foreground_load_ = true; 150 got_first_foreground_load_ = true;
96 base::TimeDelta time_to_load = 151 base::TimeDelta time_to_load =
97 base::TimeTicks::Now() - restore_started_; 152 base::TimeTicks::Now() - restore_started_;
98 UMA_HISTOGRAM_CUSTOM_TIMES("SessionRestore.ForegroundTabFirstLoaded", 153 UMA_HISTOGRAM_CUSTOM_TIMES("SessionRestore.ForegroundTabFirstLoaded",
99 time_to_load, 154 time_to_load,
100 base::TimeDelta::FromMilliseconds(10), 155 base::TimeDelta::FromMilliseconds(10),
101 base::TimeDelta::FromSeconds(100), 100); 156 base::TimeDelta::FromSeconds(100), 100);
102 // Record a time for the number of tabs, to help track down 157 // Record a time for the number of tabs, to help track down
103 // contention. 158 // contention.
104 std::string time_for_count = base::StringPrintf( 159 std::string time_for_count = base::StringPrintf(
105 "SessionRestore.ForegroundTabFirstLoaded_%d", tab_count_); 160 "SessionRestore.ForegroundTabFirstLoaded_%d", tab_count_);
106 base::HistogramBase* counter_for_count = 161 base::HistogramBase* counter_for_count =
107 base::Histogram::FactoryTimeGet( 162 base::Histogram::FactoryTimeGet(
108 time_for_count, base::TimeDelta::FromMilliseconds(10), 163 time_for_count, base::TimeDelta::FromMilliseconds(10),
109 base::TimeDelta::FromSeconds(100), 100, 164 base::TimeDelta::FromSeconds(100), 100,
110 base::Histogram::kUmaTargetedHistogramFlag); 165 base::Histogram::kUmaTargetedHistogramFlag);
111 counter_for_count->AddTime(time_to_load); 166 counter_for_count->AddTime(time_to_load);
112 } 167 }
113 break; 168 break;
114 } 169 }
115 case content::NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE: { 170 case content::NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE: {
171 // This notification is across all tabs in the browser so notifications
172 // will arrive for tabs that the collector is not explicitly tracking.
173
174 // Only process this event if first paint hasn't been seen and this is a
175 // paint of a visible tab.
116 RenderWidgetHost* render_widget_host = 176 RenderWidgetHost* render_widget_host =
117 content::Source<RenderWidgetHost>(source).ptr(); 177 content::Source<RenderWidgetHost>(source).ptr();
118 if (!got_first_paint_ && render_widget_host->GetView() && 178 if (!got_first_paint_ &&
179 render_widget_host->GetView() &&
119 render_widget_host->GetView()->IsShowing()) { 180 render_widget_host->GetView()->IsShowing()) {
120 if (render_widget_hosts_to_paint_.find(render_widget_host) != 181 // If this is a paint for a tab that is explicitly being tracked for
121 render_widget_hosts_to_paint_.end()) { 182 // paint events then record the appropriate UMA statistic.
183 auto render_widget_host_it =
184 render_widget_hosts_to_paint_.find(render_widget_host);
185 if (render_widget_host_it != render_widget_hosts_to_paint_.end()) {
186 // Stop tracking this tab.
187 render_widget_hosts_to_paint_.erase(render_widget_host_it);
188
122 // Got a paint for one of our renderers, so record time. 189 // Got a paint for one of our renderers, so record time.
123 got_first_paint_ = true; 190 got_first_paint_ = true;
124 base::TimeDelta time_to_paint = 191 base::TimeDelta time_to_paint =
125 base::TimeTicks::Now() - restore_started_; 192 base::TimeTicks::Now() - restore_started_;
126 // TODO(danduong): to remove this with 467680, to make sure we 193 // TODO(danduong): to remove this with 467680, to make sure we
127 // don't forget to clean this up. 194 // don't forget to clean this up.
128 UMA_HISTOGRAM_CUSTOM_TIMES("SessionRestore.ForegroundTabFirstPaint", 195 UMA_HISTOGRAM_CUSTOM_TIMES("SessionRestore.ForegroundTabFirstPaint",
129 time_to_paint, 196 time_to_paint,
130 base::TimeDelta::FromMilliseconds(10), 197 base::TimeDelta::FromMilliseconds(10),
131 base::TimeDelta::FromSeconds(100), 100); 198 base::TimeDelta::FromSeconds(100), 100);
132 // Record a time for the number of tabs, to help track down 199 // Record a time for the number of tabs, to help track down
133 // contention. 200 // contention.
134 std::string time_for_count = base::StringPrintf( 201 std::string time_for_count = base::StringPrintf(
135 "SessionRestore.ForegroundTabFirstPaint_%d", tab_count_); 202 "SessionRestore.ForegroundTabFirstPaint_%d", tab_count_);
136 base::HistogramBase* counter_for_count = 203 base::HistogramBase* counter_for_count =
137 base::Histogram::FactoryTimeGet( 204 base::Histogram::FactoryTimeGet(
138 time_for_count, base::TimeDelta::FromMilliseconds(10), 205 time_for_count, base::TimeDelta::FromMilliseconds(10),
139 base::TimeDelta::FromSeconds(100), 100, 206 base::TimeDelta::FromSeconds(100), 100,
140 base::Histogram::kUmaTargetedHistogramFlag); 207 base::Histogram::kUmaTargetedHistogramFlag);
141 counter_for_count->AddTime(time_to_paint); 208 counter_for_count->AddTime(time_to_paint);
142 UMA_HISTOGRAM_CUSTOM_TIMES("SessionRestore.ForegroundTabFirstPaint2", 209 UMA_HISTOGRAM_CUSTOM_TIMES(
143 time_to_paint, 210 "SessionRestore.ForegroundTabFirstPaint2",
144 base::TimeDelta::FromMilliseconds(100), 211 time_to_paint,
145 base::TimeDelta::FromMinutes(16), 50); 212 base::TimeDelta::FromMilliseconds(100),
213 base::TimeDelta::FromMinutes(16), 50);
146 // Record a time for the number of tabs, to help track down 214 // Record a time for the number of tabs, to help track down
147 // contention. 215 // contention.
148 std::string time_for_count2 = base::StringPrintf( 216 std::string time_for_count2 = base::StringPrintf(
149 "SessionRestore.ForegroundTabFirstPaint2_%d", tab_count_); 217 "SessionRestore.ForegroundTabFirstPaint2_%d", tab_count_);
150 base::HistogramBase* counter_for_count2 = 218 base::HistogramBase* counter_for_count2 =
151 base::Histogram::FactoryTimeGet( 219 base::Histogram::FactoryTimeGet(
152 time_for_count2, base::TimeDelta::FromMilliseconds(100), 220 time_for_count2, base::TimeDelta::FromMilliseconds(100),
153 base::TimeDelta::FromMinutes(16), 50, 221 base::TimeDelta::FromMinutes(16), 50,
154 base::Histogram::kUmaTargetedHistogramFlag); 222 base::Histogram::kUmaTargetedHistogramFlag);
155 counter_for_count2->AddTime(time_to_paint); 223 counter_for_count2->AddTime(time_to_paint);
156 } else if (render_widget_hosts_loading_.find(render_widget_host) == 224 } else if (render_widget_hosts_loading_.find(render_widget_host) ==
157 render_widget_hosts_loading_.end()) { 225 render_widget_hosts_loading_.end()) {
158 // If this is a host for a tab we're not loading some other tab 226 // If this is a host for a tab we're not tracking then some other tab
159 // has rendered and there's no point tracking the time. This could 227 // has rendered and there's no point tracking the time. This could
160 // happen because the user opened a different tab or restored tabs 228 // happen because the user opened a different tab or restored tabs
161 // to an already existing browser and an existing tab painted. 229 // to an already existing browser and an existing tab painted.
162 got_first_paint_ = true; 230 got_first_paint_ = true;
163 } 231 }
232
233 if (got_first_paint_) {
234 // If the first paint has been observed the entire to-paint tracking
235 // mechanism is no longer needed.
236 registrar_.Remove(
237 this,
238 content::NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE,
239 content::NotificationService::AllSources());
240 render_widget_hosts_to_paint_.clear();
241 }
164 } 242 }
165 break; 243 break;
166 } 244 }
167 default: 245 default:
168 NOTREACHED() << "Unknown notification received:" << type; 246 NOTREACHED() << "Unknown notification received:" << type;
169 break; 247 break;
170 } 248 }
171 249
172 // Check if we are done and if so, reset |this_retainer_| as the collector no 250 // If non-deferred tabs are no longer being tracked then detach this collector
173 // longer needs to stay alive. 251 // from being the shared collector. This allows new session restores to get
174 if ((got_first_paint_ || render_widget_hosts_to_paint_.empty()) && 252 // new stats collectors. It also means that multiple stats collectors can
175 tabs_tracked_.empty() && render_widget_hosts_loading_.empty()) 253 // exist simultaneously.
254 if (shared_collector_ == this && DoneTrackingNonDeferredTabs())
255 shared_collector_ = nullptr;
256
257 // If tracking is completely finished destroy this stats collector.
258 if (shared_collector_ != this && DoneTracking())
176 this_retainer_ = nullptr; 259 this_retainer_ = nullptr;
177 } 260 }
178 261
179 void SessionRestoreStatsCollector::AddTabs( 262 void SessionRestoreStatsCollector::AddTabs(
180 const std::vector<SessionRestoreDelegate::RestoredTab>& tabs) { 263 const std::vector<SessionRestoreDelegate::RestoredTab>& tabs) {
264 // A new session restore is starting.
265 if (tab_count_ == 0) {
266 // Each session restore makes a call to AddTabs with all of its tabs to be
267 // restored all at once. Record statistics about all simultaneous session
268 // restores (ie: multi-profile) as a whole.
269 UMA_HISTOGRAM_COUNTS_100(kSessionRestoreTabCount, tabs.size());
270 UMA_HISTOGRAM_ENUMERATION(kSessionRestoreActions,
271 SESSION_RESTORE_ACTIONS_UMA_INITIATED,
272 SESSION_RESTORE_ACTIONS_UMA_MAX);
273 }
274
181 tab_count_ += tabs.size(); 275 tab_count_ += tabs.size();
182 for (auto& tab : tabs) { 276 for (auto& tab : tabs) {
277 // Record actions for each individual tab.
278 UMA_HISTOGRAM_ENUMERATION(kSessionRestoreTabActions,
279 SESSION_RESTORE_TAB_ACTIONS_UMA_TAB_CREATED,
280 SESSION_RESTORE_TAB_ACTIONS_UMA_MAX);
281
183 RegisterForNotifications(&tab.contents()->GetController()); 282 RegisterForNotifications(&tab.contents()->GetController());
184 if (tab.is_active()) { 283 if (tab.is_active()) {
185 RenderWidgetHost* render_widget_host = 284 RenderWidgetHost* render_widget_host =
186 GetRenderWidgetHost(&tab.contents()->GetController()); 285 GetRenderWidgetHost(&tab.contents()->GetController());
187 render_widget_hosts_loading_.insert(render_widget_host); 286 render_widget_hosts_loading_.insert(
287 std::make_pair(render_widget_host, false));
188 } 288 }
189 } 289 }
190 } 290 }
191 291
292 void SessionRestoreStatsCollector::DeferTabImpl(
293 content::NavigationController* tab) {
294 auto tab_it = tabs_tracked_.find(tab);
295 // If the tab is no longer being tracked it has already started loading,
296 // likely due to user action. Ignore the call to defer the tab.
297 // TODO(chrisha): Is it worth explicitly tracking these events as well?
chrisha 2015/05/13 21:18:02 Consider this a question... your thoughts?
298 if (tab_it == tabs_tracked_.end())
299 return;
300
301 // Mark this tab as deferred, if its still being tracked. A tab should not be
302 // marked as deferred twice.
303 DCHECK(!tab_it->second);
304 tab_it->second = true;
305 ++tabs_tracked_deferred_count_;
306 ++tab_deferred_count_;
307
308 // It is possible that the tab is loading so also look in the loading render
309 // widget host map in this case.
310 auto render_widget_host = GetRenderWidgetHost(tab);
311 auto render_widget_host_it = render_widget_hosts_loading_.find(
312 render_widget_host);
313 if (render_widget_host_it != render_widget_hosts_loading_.end()) {
314 DCHECK(!render_widget_host_it->second);
315 render_widget_host_it->second = true;
316 ++render_widget_hosts_loading_deferred_count_;
317 }
318
319 // If this is the first tab being deferred indicate that the session has had
320 // deferred tabs.
321 if (tab_deferred_count_ == 1) {
322 // It is assumed that tabs are being deferred due to memory pressure as this
323 // is currently the only mechanism in which this can happen.
324 UMA_HISTOGRAM_ENUMERATION(kSessionRestoreActions,
325 SESSION_RESTORE_ACTIONS_UMA_DEFERRED_TABS,
326 SESSION_RESTORE_ACTIONS_UMA_MAX);
327 }
328
329 UMA_HISTOGRAM_ENUMERATION(
330 kSessionRestoreTabActions,
331 SESSION_RESTORE_TAB_ACTIONS_UMA_TAB_LOADING_DEFERRED,
332 SESSION_RESTORE_TAB_ACTIONS_UMA_MAX);
333 }
334
192 void SessionRestoreStatsCollector::RemoveTab(NavigationController* tab) { 335 void SessionRestoreStatsCollector::RemoveTab(NavigationController* tab) {
336 // Stop observing this tab.
193 registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, 337 registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
194 content::Source<WebContents>(tab->GetWebContents())); 338 content::Source<WebContents>(tab->GetWebContents()));
195 registrar_.Remove(this, content::NOTIFICATION_LOAD_STOP, 339 registrar_.Remove(this, content::NOTIFICATION_LOAD_STOP,
196 content::Source<NavigationController>(tab)); 340 content::Source<NavigationController>(tab));
197 registrar_.Remove(this, content::NOTIFICATION_LOAD_START, 341 registrar_.Remove(this, content::NOTIFICATION_LOAD_START,
198 content::Source<NavigationController>(tab)); 342 content::Source<NavigationController>(tab));
343
344 // Remove the tab from the tracked_tabs map and be sure to update the count
345 // of deferred tracked tabs if necessary.
346 auto tab_it = tabs_tracked_.find(tab);
347 bool is_deferred = tab_it->second;
348 tabs_tracked_.erase(tab_it);
349 if (is_deferred)
350 --tabs_tracked_deferred_count_;
351
352 // Keep track of the maximum number of tabs that are loading at the same time.
353 // NOTE: This counts session restore loaded tabs and *user* loaded tabs,
354 // both deferred and otherwise. This preserves the original behaviour of
355 // this metric.
199 if (render_widget_hosts_loading_.size() > max_parallel_tab_loads_) 356 if (render_widget_hosts_loading_.size() > max_parallel_tab_loads_)
200 max_parallel_tab_loads_ = render_widget_hosts_loading_.size(); 357 max_parallel_tab_loads_ = render_widget_hosts_loading_.size();
358
359 // Remove the tab from the loading render widget host map. If the tab is
360 // present in this map and deferred, then also update the deferred count.
201 RenderWidgetHost* render_widget_host = GetRenderWidgetHost(tab); 361 RenderWidgetHost* render_widget_host = GetRenderWidgetHost(tab);
202 render_widget_hosts_loading_.erase(render_widget_host); 362 if (is_deferred && render_widget_hosts_loading_.erase(render_widget_host))
203 tabs_tracked_.erase(tab); 363 --render_widget_hosts_loading_deferred_count_;
204 364
205 // If there are no more tabs loading or being tracked, restore is done and 365 // Calculate the number of non-deferred tracked and loading tabs. These are
206 // record the time. Note that we are not yet finished, as we might still be 366 // used to determine whether session restore has completed tab loading.
207 // waiting for our first paint, which can happen after all tabs are done 367 size_t tracked = tabs_tracked_.size() - tabs_tracked_deferred_count_;
208 // loading. 368 size_t loading = render_widget_hosts_loading_.size() -
209 // TODO(georgesak): review behaviour of ForegroundTabFirstPaint. 369 render_widget_hosts_loading_deferred_count_;
210 if (tabs_tracked_.empty() && render_widget_hosts_loading_.empty()) { 370
371 // If there are no more non-deferred tabs loading or being tracked, the active
372 // portion of restore is done so record the time. Note that stats collection
373 // is not yet finished, as there can be deferred tabs and pending paint
374 // events.
375 // NOTE: This is only concerned with tabs that are being actively tracked,
376 // and not deferred tabs. Deferred tabs are still tracked, but don't
377 // affect the AllTabsLoaded metric.
378 // TODO(georgesak): Review behaviour of ForegroundTabFirstPaint.
379 if (tracked == 0 && loading == 0) {
211 base::TimeDelta time_to_load = base::TimeTicks::Now() - restore_started_; 380 base::TimeDelta time_to_load = base::TimeTicks::Now() - restore_started_;
212 UMA_HISTOGRAM_CUSTOM_TIMES("SessionRestore.AllTabsLoaded", time_to_load, 381 UMA_HISTOGRAM_CUSTOM_TIMES("SessionRestore.AllTabsLoaded", time_to_load,
213 base::TimeDelta::FromMilliseconds(10), 382 base::TimeDelta::FromMilliseconds(10),
214 base::TimeDelta::FromSeconds(100), 100); 383 base::TimeDelta::FromSeconds(100), 100);
215 // Record a time for the number of tabs, to help track down contention. 384 // Record a time for the number of tabs, to help track down contention.
216 std::string time_for_count = 385 std::string time_for_count =
217 base::StringPrintf("SessionRestore.AllTabsLoaded_%d", tab_count_); 386 base::StringPrintf("SessionRestore.AllTabsLoaded_%d", tab_count_);
218 base::HistogramBase* counter_for_count = base::Histogram::FactoryTimeGet( 387 base::HistogramBase* counter_for_count = base::Histogram::FactoryTimeGet(
219 time_for_count, base::TimeDelta::FromMilliseconds(10), 388 time_for_count, base::TimeDelta::FromMilliseconds(10),
220 base::TimeDelta::FromSeconds(100), 100, 389 base::TimeDelta::FromSeconds(100), 100,
221 base::Histogram::kUmaTargetedHistogramFlag); 390 base::Histogram::kUmaTargetedHistogramFlag);
222 counter_for_count->AddTime(time_to_load); 391 counter_for_count->AddTime(time_to_load);
223 392
224 UMA_HISTOGRAM_COUNTS_100("SessionRestore.ParallelTabLoads", 393 UMA_HISTOGRAM_COUNTS_100("SessionRestore.ParallelTabLoads",
225 max_parallel_tab_loads_); 394 max_parallel_tab_loads_);
226 } 395 }
227 } 396 }
228 397
229 void SessionRestoreStatsCollector::RegisterForNotifications( 398 void SessionRestoreStatsCollector::RegisterForNotifications(
230 NavigationController* tab) { 399 NavigationController* tab) {
231 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, 400 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
232 content::Source<WebContents>(tab->GetWebContents())); 401 content::Source<WebContents>(tab->GetWebContents()));
233 registrar_.Add(this, content::NOTIFICATION_LOAD_STOP, 402 registrar_.Add(this, content::NOTIFICATION_LOAD_STOP,
234 content::Source<NavigationController>(tab)); 403 content::Source<NavigationController>(tab));
235 registrar_.Add(this, content::NOTIFICATION_LOAD_START, 404 registrar_.Add(this, content::NOTIFICATION_LOAD_START,
236 content::Source<NavigationController>(tab)); 405 content::Source<NavigationController>(tab));
237 tabs_tracked_.insert(tab); 406 // All tabs are non-deferred to start with.
407 tabs_tracked_.insert(std::make_pair(tab, false));
238 } 408 }
239 409
240 RenderWidgetHost* SessionRestoreStatsCollector::GetRenderWidgetHost( 410 RenderWidgetHost* SessionRestoreStatsCollector::GetRenderWidgetHost(
241 NavigationController* tab) { 411 NavigationController* tab) {
242 WebContents* web_contents = tab->GetWebContents(); 412 WebContents* web_contents = tab->GetWebContents();
243 if (web_contents) { 413 if (web_contents) {
244 content::RenderWidgetHostView* render_widget_host_view = 414 content::RenderWidgetHostView* render_widget_host_view =
245 web_contents->GetRenderWidgetHostView(); 415 web_contents->GetRenderWidgetHostView();
246 if (render_widget_host_view) 416 if (render_widget_host_view)
247 return render_widget_host_view->GetRenderWidgetHost(); 417 return render_widget_host_view->GetRenderWidgetHost();
248 } 418 }
249 return nullptr; 419 return nullptr;
250 } 420 }
251 421
422 bool SessionRestoreStatsCollector::IsDeferred(
423 content::NavigationController* tab) const {
424 auto tab_it = tabs_tracked_.find(tab);
425 DCHECK(tab_it != tabs_tracked_.end());
426 return tab_it->second;
427 }
428
429 bool SessionRestoreStatsCollector::DoneTrackingNonDeferredTabs() const {
430 // If first paint hasn't been seen and tabs are being tracked for paints
431 // (ie: a first paint could yet be seen) then the stats collector is not done.
432 if (!got_first_paint_ && !render_widget_hosts_to_paint_.empty())
433 return false;
434
435 // No non-deferred tabs should be in the tracked map.
436 size_t tracked = tabs_tracked_.size() - tabs_tracked_deferred_count_;
437 if (tracked > 0)
438 return false;
439
440 // No non-deferred tabs should be in the loading map.
441 size_t loading = render_widget_hosts_loading_.size() -
442 render_widget_hosts_loading_deferred_count_;
443 if (loading > 0)
444 return false;
445
446 return true;
447 }
448
449 bool SessionRestoreStatsCollector::DoneTracking() const {
450 // This should only be called once all non-deferred tabs have finished
451 // tracking.
452 DCHECK(DoneTrackingNonDeferredTabs());
453 return render_widget_hosts_loading_.empty() && tabs_tracked_.empty();
454 }
455
252 // static 456 // static
253 SessionRestoreStatsCollector* SessionRestoreStatsCollector::shared_collector_ = 457 SessionRestoreStatsCollector* SessionRestoreStatsCollector::shared_collector_ =
254 nullptr; 458 nullptr;
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698