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

Unified 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: Refactored per sky@'s suggestion. 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/sessions/session_restore_stats_collector.cc
diff --git a/chrome/browser/sessions/session_restore_stats_collector.cc b/chrome/browser/sessions/session_restore_stats_collector.cc
index f593b6eb299186711d4b4546b118c676c3f6413b..c1299b2a245a6d28e75241e56ccb8b1fd6133c0b 100644
--- a/chrome/browser/sessions/session_restore_stats_collector.cc
+++ b/chrome/browser/sessions/session_restore_stats_collector.cc
@@ -17,6 +17,51 @@ using content::NavigationController;
using content::RenderWidgetHost;
using content::WebContents;
+namespace {
+
+// Metric names.
+const char kSessionRestoreActions[] = "SessionRestore.Actions";
+const char kSessionRestoreTabCount[] = "SessionRestore.TabCount";
+const char kSessionRestoreTabActions[] = "SessionRestore.TabActions";
+
+// The enumeration values stored in the kSessionRestoreActions histogram.
+enum SessionRestoreActionsUma {
+ // Counts the total number of session restores that have occurred.
+ kSessionRestoreActionsUma_Initiated = 0,
sky 2015/05/12 15:27:56 SESSION_RESTORE_ACTION_UMA_INITIATED (see chrome s
chrisha 2015/05/13 21:18:01 Done.
+ // Counts the number of session restores that have been deferred tab loadings
+ // for whatever reason (almost certainly due to memory pressure).
+ kSessionRestoreActionsUma_DeferredTabs = 1,
+ // The size of this enum. Must be the last entry.
+ kSessionRestoreActionsUma_Max,
+};
+
+// The enumeration of values stored in the kSessionRestoreTabActions histogram.
+enum SessionRestoreTabActionsUma {
+ // Incremented for each tab created in a session restore.
+ kSessionRestoreTabActionsUma_TabCreated = 0,
+ // Incremented for each tab started to load by the session restore.
+ kSessionRestoreTabActionsUma_TabLoading = 1,
+ // Incremented for each tab that session restore decides not to load.
+ kSessionRestoreTabActionsUma_TabLoadingDeferred = 2,
+ // Incremented for each tab that is successfully loaded.
+ kSessionRestoreTabActionsUma_TabLoaded = 3,
+ // Incremented for each session-restore-deferred tab that subsequently starts
+ // to load.
+ kSessionRestoreTabActionsUma_DeferredTabLoading = 4,
+ // Incremented for each non-deferred not-yet-loaded tab closed by the user.
+ kSessionRestoreTabActionsUma_NonDeferredNotLoadingTabClosed = 5,
+ // Incremented for each non-deferred actively-loading tab closed by the user.
+ kSessionRestoreTabActionsUma_NonDeferredLoadingTabClosed = 6,
+ // Incremented for each deferred not-yet-loaded tab closed by the user.
+ kSessionRestoreTabActionsUma_DeferredNotLoadingTabClosed = 7,
+ // Incremented for each deferred actively-loading tab closed by the user.
+ kSessionRestoreTabActionsUma_DeferredLoadingTabClosed = 8,
+ // The size of this enum. Must be the last entry.
+ kSessionRestoreTabActionsUma_Max,
+};
+
+} // namespace
+
// static
void SessionRestoreStatsCollector::TrackTabs(
const std::vector<SessionRestoreDelegate::RestoredTab>& tabs,
@@ -27,12 +72,22 @@ void SessionRestoreStatsCollector::TrackTabs(
shared_collector_->AddTabs(tabs);
}
+// static
+void SessionRestoreStatsCollector::DeferTab(
+ content::NavigationController* tab) {
+ // It only makes sense for this to have been called *after* DeferTab, so a
+ // stats collector will always exist.
sky 2015/05/12 15:27:56 DCHECK(shared_collector_)
chrisha 2015/05/13 21:18:01 Done.
+ shared_collector_->DeferTabImpl(tab);
+}
+
SessionRestoreStatsCollector::SessionRestoreStatsCollector(
const base::TimeTicks& restore_started)
: got_first_foreground_load_(false),
got_first_paint_(false),
restore_started_(restore_started),
tab_count_(0),
+ tab_deferred_count_(0),
+ session_restore_id_(0),
max_parallel_tab_loads_(0) {
this_retainer_ = this;
registrar_.Add(
@@ -58,6 +113,16 @@ void SessionRestoreStatsCollector::Observe(
// a load has finished.
NavigationController* tab =
content::Source<NavigationController>(source).ptr();
+ bool is_deferred = IsDeferred(tab);
+
+ // Record the appropriate tab loading event type.
+ auto tab_action =
+ is_deferred ? kSessionRestoreTabActionsUma_TabLoading :
+ kSessionRestoreTabActionsUma_DeferredTabLoading;
+ UMA_HISTOGRAM_ENUMERATION(kSessionRestoreTabActions,
+ tab_action,
+ kSessionRestoreTabActionsUma_Max);
+
RenderWidgetHost* render_widget_host = GetRenderWidgetHost(tab);
DCHECK(render_widget_host);
render_widget_hosts_loading_.insert(render_widget_host);
@@ -65,15 +130,46 @@ void SessionRestoreStatsCollector::Observe(
}
case content::NOTIFICATION_WEB_CONTENTS_DESTROYED: {
WebContents* web_contents = content::Source<WebContents>(source).ptr();
- RemoveTab(&web_contents->GetController());
+ NavigationController* tab = &web_contents->GetController();
+ bool is_deferred = IsDeferred(tab);
+
+ // Record a tab action for the tab that is being closed. If this tab is
+ // loading it will have a RenderWidgetHost in the tracking set.
+ RenderWidgetHost* render_widget_host = GetRenderWidgetHost(tab);
+ auto tab_action = kSessionRestoreTabActionsUma_Max;
+ if (render_widget_hosts_loading_.count(render_widget_host) > 0) {
+ // This tab is loading.
+ tab_action = is_deferred ?
+ kSessionRestoreTabActionsUma_DeferredLoadingTabClosed :
+ kSessionRestoreTabActionsUma_NonDeferredLoadingTabClosed;
+ } else {
+ // This tab is not loading.
+ tab_action = is_deferred ?
+ kSessionRestoreTabActionsUma_DeferredNotLoadingTabClosed :
+ kSessionRestoreTabActionsUma_NonDeferredNotLoadingTabClosed;
+ }
+ UMA_HISTOGRAM_ENUMERATION(kSessionRestoreTabActions,
+ tab_action,
+ kSessionRestoreTabActionsUma_Max);
+
+ RemoveTab(is_deferred, tab);
break;
}
case content::NOTIFICATION_LOAD_STOP: {
NavigationController* tab =
content::Source<NavigationController>(source).ptr();
+ bool is_deferred = IsDeferred(tab);
RenderWidgetHost* render_widget_host = GetRenderWidgetHost(tab);
render_widget_hosts_to_paint_.insert(render_widget_host);
- RemoveTab(tab);
+
+ // Note the fact that this tab loaded.
+ UMA_HISTOGRAM_ENUMERATION(kSessionRestoreTabActions,
+ kSessionRestoreTabActionsUma_TabLoaded,
+ kSessionRestoreTabActionsUma_Max);
+
+ RemoveTab(is_deferred, tab);
+
+ // Update UMA stats for foreground tabs.
if (!got_first_foreground_load_ && render_widget_host &&
render_widget_host->GetView() &&
render_widget_host->GetView()->IsShowing()) {
@@ -163,8 +259,25 @@ void SessionRestoreStatsCollector::Observe(
void SessionRestoreStatsCollector::AddTabs(
const std::vector<SessionRestoreDelegate::RestoredTab>& tabs) {
+ // Increment the session restore ID so to distinguish which tabs belong to
+ // which conceptual session restore.
+ ++session_restore_id_;
+
+ // Each session restore makes a call to AddTabs with all of its tabs to be
+ // restored all at once. Record statistics about the session restore as a
+ // whole.
+ UMA_HISTOGRAM_COUNTS_100(kSessionRestoreTabCount, tabs.size());
+ UMA_HISTOGRAM_ENUMERATION(kSessionRestoreActions,
+ kSessionRestoreActionsUma_Initiated,
+ kSessionRestoreActionsUma_Max);
+
tab_count_ += tabs.size();
for (auto& tab : tabs) {
+ // Record actions for each individual tab.
+ UMA_HISTOGRAM_ENUMERATION(kSessionRestoreTabActions,
+ kSessionRestoreTabActionsUma_TabCreated,
+ kSessionRestoreTabActionsUma_Max);
+
RegisterForNotifications(&tab.contents()->GetController());
if (tab.is_active()) {
RenderWidgetHost* render_widget_host =
@@ -174,32 +287,74 @@ void SessionRestoreStatsCollector::AddTabs(
}
}
-void SessionRestoreStatsCollector::RemoveTab(NavigationController* tab) {
+void SessionRestoreStatsCollector::DeferTabImpl(
+ content::NavigationController* tab) {
+ // We simply move this tab from the tracked set to the deferred set.
+ ++tab_deferred_count_;
+ auto tracked_it = tabs_tracked_.find(tab);
+ int session_id = tracked_it->second;
+ tabs_deferred_.insert(*tracked_it);
+ tabs_tracked_.erase(tracked_it);
+
+ // Only indicate that the session has had deferred tabs if this is the first
+ // tab associated with that session being deferred.
+ if (deferred_tabs_seen_.insert(session_id).second) {
+ // It is assumed that tabs are being deferred due to memory pressure as this
+ // is currently the only mechanism in which this can happen.
+ UMA_HISTOGRAM_ENUMERATION(kSessionRestoreActions,
+ kSessionRestoreActionsUma_DeferredTabs,
+ kSessionRestoreActionsUma_Max);
+ }
+
+ UMA_HISTOGRAM_ENUMERATION(kSessionRestoreTabActions,
+ kSessionRestoreTabActionsUma_TabLoadingDeferred,
+ kSessionRestoreTabActionsUma_Max);
+}
+
+void SessionRestoreStatsCollector::RemoveTab(bool is_deferred,
+ NavigationController* tab) {
+ // Stop observing this tab.
registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
content::Source<WebContents>(tab->GetWebContents()));
registrar_.Remove(this, content::NOTIFICATION_LOAD_STOP,
content::Source<NavigationController>(tab));
registrar_.Remove(this, content::NOTIFICATION_LOAD_START,
content::Source<NavigationController>(tab));
- if (render_widget_hosts_loading_.size() > max_parallel_tab_loads_)
+
+ // Keep track of the maximum number of automatically loaded tabs that are
+ // loading at the same time.
+ if (!is_deferred &&
+ render_widget_hosts_loading_.size() > max_parallel_tab_loads_) {
max_parallel_tab_loads_ = render_widget_hosts_loading_.size();
+ }
+
RenderWidgetHost* render_widget_host = GetRenderWidgetHost(tab);
render_widget_hosts_loading_.erase(render_widget_host);
- tabs_tracked_.erase(tab);
+
+ // Remove the tab from the appropriate list.
+ if (is_deferred) {
+ tabs_deferred_.erase(tab);
+ } else {
+ tabs_tracked_.erase(tab);
+ }
sky 2015/05/12 15:27:56 Would be nice to have some DCHECKs here that tab i
chrisha 2015/05/13 21:18:02 I moved to using a map that tracks the 'deferred'
// If there are no more tabs loading or being tracked, restore is done and
// record the time. Note that we are not yet finished, as we might still be
// waiting for our first paint, which can happen after all tabs are done
// loading.
- // TODO(georgesak): review behaviour of ForegroundTabFirstPaint.
+ // NOTE: This is only concerned with tabs that are being actively tracked,
+ // and not deferred tabs. Deferred tabs are still tracked, but don't
+ // affect the AllTabsLoaded metric.
+ // TODO(georgesak): Review behaviour of ForegroundTabFirstPaint.
if (tabs_tracked_.empty() && render_widget_hosts_loading_.empty()) {
sky 2015/05/12 15:27:56 Lets say tabs_tracked_ goes empty, adoesn't that m
chrisha 2015/05/13 21:18:02 Yes, that's true. This is no worse than before in
sky 2015/05/14 00:12:40 Not sure there. I think you're change makes it wor
chrisha 2015/05/14 21:27:02 The 'deferred state' of a tab doesn't change it's
sky 2015/05/14 21:51:50 Ok.
base::TimeDelta time_to_load = base::TimeTicks::Now() - restore_started_;
UMA_HISTOGRAM_CUSTOM_TIMES("SessionRestore.AllTabsLoaded", time_to_load,
base::TimeDelta::FromMilliseconds(10),
base::TimeDelta::FromSeconds(100), 100);
// Record a time for the number of tabs, to help track down contention.
+ int tabs_loaded = tab_count_ - tab_deferred_count_;
std::string time_for_count =
- base::StringPrintf("SessionRestore.AllTabsLoaded_%d", tab_count_);
+ base::StringPrintf("SessionRestore.AllTabsLoaded_%d", tabs_loaded);
base::HistogramBase* counter_for_count = base::Histogram::FactoryTimeGet(
time_for_count, base::TimeDelta::FromMilliseconds(10),
base::TimeDelta::FromSeconds(100), 100,
@@ -219,7 +374,7 @@ void SessionRestoreStatsCollector::RegisterForNotifications(
content::Source<NavigationController>(tab));
registrar_.Add(this, content::NOTIFICATION_LOAD_START,
content::Source<NavigationController>(tab));
- tabs_tracked_.insert(tab);
+ tabs_tracked_.insert(std::make_pair(tab, session_restore_id_));
}
RenderWidgetHost* SessionRestoreStatsCollector::GetRenderWidgetHost(
@@ -234,6 +389,13 @@ RenderWidgetHost* SessionRestoreStatsCollector::GetRenderWidgetHost(
return nullptr;
}
+bool SessionRestoreStatsCollector::IsDeferred(
+ content::NavigationController* tab) {
+ if (tabs_deferred_.count(tab) > 0)
sky 2015/05/12 15:27:56 nit: return tabs_deffered_.count(tab) > 0
chrisha 2015/05/13 21:18:01 (I have a tendency to write code this way because
+ return true;
+ return false;
+}
+
// static
SessionRestoreStatsCollector* SessionRestoreStatsCollector::shared_collector_ =
nullptr;

Powered by Google App Engine
This is Rietveld 408576698