diff options
Diffstat (limited to 'chrome/browser/sessions/session_restore_stats_collector.cc')
-rw-r--r-- | chrome/browser/sessions/session_restore_stats_collector.cc | 565 |
1 files changed, 403 insertions, 162 deletions
diff --git a/chrome/browser/sessions/session_restore_stats_collector.cc b/chrome/browser/sessions/session_restore_stats_collector.cc index f892d1a..262500f 100644 --- a/chrome/browser/sessions/session_restore_stats_collector.cc +++ b/chrome/browser/sessions/session_restore_stats_collector.cc @@ -8,58 +8,137 @@ #include "base/metrics/histogram.h" #include "base/strings/stringprintf.h" +#include "base/time/default_tick_clock.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/notification_types.h" #include "content/public/browser/render_widget_host_view.h" #include "content/public/browser/web_contents.h" +namespace { + using content::NavigationController; using content::RenderWidgetHost; +using content::Source; using content::WebContents; -// static -void SessionRestoreStatsCollector::TrackTabs( - const std::vector<SessionRestoreDelegate::RestoredTab>& tabs, - const base::TimeTicks& restore_started) { - if (!shared_collector_) - shared_collector_ = new SessionRestoreStatsCollector(restore_started); +// The enumeration values stored in the "SessionRestore.Actions" histogram. +enum SessionRestoreActionsUma { + // Counts the total number of session restores that have occurred. + SESSION_RESTORE_ACTIONS_UMA_INITIATED = 0, + // Counts the number of session restores that have seen deferred tab loadings + // for whatever reason (almost certainly due to memory pressure). + SESSION_RESTORE_ACTIONS_UMA_DEFERRED_TABS = 1, + // The size of this enum. Must be the last entry. + SESSION_RESTORE_ACTIONS_UMA_MAX, +}; - shared_collector_->AddTabs(tabs); +// Emits a SessionRestore.Actions UMA event. +void EmitUmaSessionRestoreActionEvent(SessionRestoreActionsUma action) { + UMA_HISTOGRAM_ENUMERATION("SessionRestore.Actions", action, + SESSION_RESTORE_ACTIONS_UMA_MAX); } -// static -void SessionRestoreStatsCollector::TrackActiveTabs( - const std::vector<SessionRestoreDelegate::RestoredTab>& tabs, - const base::TimeTicks& restore_started) { - if (!shared_collector_) - shared_collector_ = new SessionRestoreStatsCollector(restore_started); +// The enumeration of values stored in the "SessionRestore.TabActions" +// histogram. +enum SessionRestoreTabActionsUma { + // Incremented for each tab created in a session restore. + SESSION_RESTORE_TAB_ACTIONS_UMA_TAB_CREATED = 0, + // Incremented for each tab that session restore decides not to load. + SESSION_RESTORE_TAB_ACTIONS_UMA_TAB_LOADING_DEFERRED = 1, + // Incremented for each tab that is successfully loaded. + SESSION_RESTORE_TAB_ACTIONS_UMA_TAB_LOADED = 2, + // Incremented for each session-restore-deferred tab that is subsequently + // loaded. + SESSION_RESTORE_TAB_ACTIONS_UMA_DEFERRED_TAB_LOADED = 3, + // The size of this enum. Must be the last entry. + SESSION_RESTORE_TAB_ACTIONS_UMA_MAX, +}; - std::vector<SessionRestoreDelegate::RestoredTab> active_tabs; - for (auto tab : tabs) { - if (tab.is_active()) - active_tabs.push_back(tab); - } - shared_collector_->AddTabs(active_tabs); +// Emits a SessionRestore.TabActions UMA event. +void EmitUmaSessionRestoreTabActionEvent(SessionRestoreTabActionsUma action) { + UMA_HISTOGRAM_ENUMERATION("SessionRestore.TabActions", action, + SESSION_RESTORE_TAB_ACTIONS_UMA_MAX); +} + +} // namespace + +SessionRestoreStatsCollector::TabLoaderStats::TabLoaderStats() + : tab_count(0u), tabs_loaded(0u), parallel_tab_loads(0u) { +} + +SessionRestoreStatsCollector::TabState::TabState( + NavigationController* controller) + : controller(controller), + render_widget_host(nullptr), + is_deferred(false), + loading_state(TAB_IS_NOT_LOADING) { } SessionRestoreStatsCollector::SessionRestoreStatsCollector( - const base::TimeTicks& restore_started) - : got_first_foreground_load_(false), + const base::TimeTicks& restore_started, + scoped_ptr<StatsReportingDelegate> reporting_delegate) + : done_tracking_non_deferred_tabs_(false), + got_first_foreground_load_(false), got_first_paint_(false), restore_started_(restore_started), - tab_count_(0), - max_parallel_tab_loads_(0) { + waiting_for_load_tab_count_(0u), + loading_tab_count_(0u), + deferred_tab_count_(0u), + tick_clock_(new base::DefaultTickClock()), + reporting_delegate_(reporting_delegate.Pass()) { this_retainer_ = this; - registrar_.Add( - this, content::NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE, - content::NotificationService::AllSources()); } SessionRestoreStatsCollector::~SessionRestoreStatsCollector() { - DCHECK((got_first_paint_ || render_widget_hosts_to_paint_.empty()) && - tabs_tracked_.empty() && render_widget_hosts_loading_.empty()); - DCHECK(shared_collector_ == this); - shared_collector_ = nullptr; +} + +void SessionRestoreStatsCollector::TrackTabs( + const std::vector<SessionRestoreDelegate::RestoredTab>& tabs) { + DCHECK(!done_tracking_non_deferred_tabs_); + + // If this is the first call to TrackTabs then start observing events. + if (tab_loader_stats_.tab_count == 0) { + registrar_.Add( + this, content::NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE, + content::NotificationService::AllSources()); + } + + tab_loader_stats_.tab_count += tabs.size(); + waiting_for_load_tab_count_ += tabs.size(); + for (const auto& tab : tabs) { + TabState* tab_state = + RegisterForNotifications(&tab.contents()->GetController()); + // Active tabs have already started loading. + if (tab.is_active()) + MarkTabAsLoading(tab_state); + } +} + +void SessionRestoreStatsCollector::DeferTab(NavigationController* tab) { + TabState* tab_state = GetTabState(tab); + + // If the tab is no longer being tracked it has already finished loading. + // This can occur if the user forces the tab to load before the entire session + // restore is over, and the TabLoader then decides it would defer loading of + // that tab. + if (!tab_state) + return; + + // Mark this tab as deferred, if its still being tracked. A tab should not be + // marked as deferred twice. + DCHECK(!tab_state->is_deferred); + tab_state->is_deferred = true; + ++deferred_tab_count_; + + // A tab that didn't start loading before it was deferred is not to be + // actively monitored for loading. + if (tab_state->loading_state == TAB_IS_NOT_LOADING) { + DCHECK_LT(0u, waiting_for_load_tab_count_); + if (--waiting_for_load_tab_count_ == 0) + ReleaseIfDoneTracking(); + } + + reporting_delegate_->ReportTabDeferred(); } void SessionRestoreStatsCollector::Observe( @@ -68,99 +147,112 @@ void SessionRestoreStatsCollector::Observe( const content::NotificationDetails& details) { switch (type) { case content::NOTIFICATION_LOAD_START: { - // Add this render_widget_host to the set of those we're waiting for - // paints on. We want to only record stats for paints that occur after - // a load has finished. - NavigationController* tab = - content::Source<NavigationController>(source).ptr(); - RenderWidgetHost* render_widget_host = GetRenderWidgetHost(tab); - DCHECK(render_widget_host); - render_widget_hosts_loading_.insert(render_widget_host); + // This occurs when a tab has started to load. This can be because of + // the tab loader (only for non-deferred tabs) or because the user clicked + // on the tab. + NavigationController* tab = Source<NavigationController>(source).ptr(); + TabState* tab_state = GetTabState(tab); + MarkTabAsLoading(tab_state); break; } case content::NOTIFICATION_WEB_CONTENTS_DESTROYED: { - WebContents* web_contents = content::Source<WebContents>(source).ptr(); - RemoveTab(&web_contents->GetController()); + // This happens when a tab has been closed. A tab can be in any state + // when this occurs. Simply stop tracking the tab. + WebContents* web_contents = Source<WebContents>(source).ptr(); + NavigationController* tab = &web_contents->GetController(); + RemoveTab(tab); break; } case content::NOTIFICATION_LOAD_STOP: { - NavigationController* tab = - content::Source<NavigationController>(source).ptr(); - RenderWidgetHost* render_widget_host = GetRenderWidgetHost(tab); - render_widget_hosts_to_paint_.insert(render_widget_host); - RemoveTab(tab); - if (!got_first_foreground_load_ && render_widget_host && - render_widget_host->GetView() && - render_widget_host->GetView()->IsShowing()) { + // This occurs to loading tabs when they have finished loading. The tab + // may or may not already have painted at this point. + + // Update the tab state and any global state as necessary. + NavigationController* tab = Source<NavigationController>(source).ptr(); + TabState* tab_state = GetTabState(tab); + DCHECK(tab_state); + tab_state->loading_state = TAB_IS_LOADED; + DCHECK_LT(0u, loading_tab_count_); + --loading_tab_count_; + if (!tab_state->is_deferred) { + DCHECK_LT(0u, waiting_for_load_tab_count_); + --waiting_for_load_tab_count_; + } + + if (tab_state->is_deferred) { + reporting_delegate_->ReportDeferredTabLoaded(); + } else { + DCHECK(!done_tracking_non_deferred_tabs_); + ++tab_loader_stats_.tabs_loaded; + } + + // Update statistics for foreground tabs. + base::TimeDelta time_to_load = tick_clock_->NowTicks() - restore_started_; + if (!got_first_foreground_load_ && tab_state->render_widget_host && + tab_state->render_widget_host->GetView() && + tab_state->render_widget_host->GetView()->IsShowing()) { got_first_foreground_load_ = true; - base::TimeDelta time_to_load = - base::TimeTicks::Now() - restore_started_; - UMA_HISTOGRAM_CUSTOM_TIMES("SessionRestore.ForegroundTabFirstLoaded", - 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. - std::string time_for_count = base::StringPrintf( - "SessionRestore.ForegroundTabFirstLoaded_%d", tab_count_); - base::HistogramBase* counter_for_count = - base::Histogram::FactoryTimeGet( - time_for_count, base::TimeDelta::FromMilliseconds(10), - base::TimeDelta::FromSeconds(100), 100, - base::Histogram::kUmaTargetedHistogramFlag); - counter_for_count->AddTime(time_to_load); + DCHECK(!done_tracking_non_deferred_tabs_); + tab_loader_stats_.foreground_tab_first_loaded = time_to_load; } + + // Update statistics for all tabs, if this wasn't a deferred tab. This is + // done here and not in ReleaseIfDoneTracking because it is possible to + // wait for a paint long after all loads have completed. + if (!done_tracking_non_deferred_tabs_ && !tab_state->is_deferred) + tab_loader_stats_.non_deferred_tabs_loaded = time_to_load; + + // By default tabs transition to being tracked for paint events after the + // load event has been seen. However, if the first paint event has already + // been seen then this is not necessary and the tab can be removed. + if (got_first_paint_) + RemoveTab(tab); + break; } case content::NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE: { + // This notification is across all tabs in the browser so notifications + // will arrive for tabs that the collector is not explicitly tracking. + + // Only process this event if first paint hasn't been seen and this is a + // paint of a visible tab. RenderWidgetHost* render_widget_host = - content::Source<RenderWidgetHost>(source).ptr(); + Source<RenderWidgetHost>(source).ptr(); if (!got_first_paint_ && render_widget_host->GetView() && render_widget_host->GetView()->IsShowing()) { - if (render_widget_hosts_to_paint_.find(render_widget_host) != - render_widget_hosts_to_paint_.end()) { - // Got a paint for one of our renderers, so record time. - got_first_paint_ = true; - base::TimeDelta time_to_paint = - base::TimeTicks::Now() - restore_started_; - // TODO(danduong): to remove this with 467680, to make sure we - // don't forget to clean this up. - UMA_HISTOGRAM_CUSTOM_TIMES("SessionRestore.ForegroundTabFirstPaint", - time_to_paint, - base::TimeDelta::FromMilliseconds(10), - base::TimeDelta::FromSeconds(100), 100); - // Record a time for the number of tabs, to help track down - // contention. - std::string time_for_count = base::StringPrintf( - "SessionRestore.ForegroundTabFirstPaint_%d", tab_count_); - base::HistogramBase* counter_for_count = - base::Histogram::FactoryTimeGet( - time_for_count, base::TimeDelta::FromMilliseconds(10), - base::TimeDelta::FromSeconds(100), 100, - base::Histogram::kUmaTargetedHistogramFlag); - counter_for_count->AddTime(time_to_paint); - UMA_HISTOGRAM_CUSTOM_TIMES("SessionRestore.ForegroundTabFirstPaint2", - time_to_paint, - base::TimeDelta::FromMilliseconds(100), - base::TimeDelta::FromMinutes(16), 50); - // Record a time for the number of tabs, to help track down - // contention. - std::string time_for_count2 = base::StringPrintf( - "SessionRestore.ForegroundTabFirstPaint2_%d", tab_count_); - base::HistogramBase* counter_for_count2 = - base::Histogram::FactoryTimeGet( - time_for_count2, base::TimeDelta::FromMilliseconds(100), - base::TimeDelta::FromMinutes(16), 50, - base::Histogram::kUmaTargetedHistogramFlag); - counter_for_count2->AddTime(time_to_paint); - } else if (render_widget_hosts_loading_.find(render_widget_host) == - render_widget_hosts_loading_.end()) { - // If this is a host for a tab we're not loading some other tab - // has rendered and there's no point tracking the time. This could + got_first_paint_ = true; + TabState* tab_state = GetTabState(render_widget_host); + if (tab_state) { + // This is a paint for a tab that is explicitly being tracked so + // update the statistics. Otherwise the host is for a tab that's not + // being tracked thus some other tab has visibility and has rendered + // and there's no point in tracking the time to first paint. This can // happen because the user opened a different tab or restored tabs - // to an already existing browser and an existing tab painted. - got_first_paint_ = true; + // to an already existing browser and an existing tab was in the + // foreground. + base::TimeDelta time_to_paint = + tick_clock_->NowTicks() - restore_started_; + DCHECK(!done_tracking_non_deferred_tabs_); + tab_loader_stats_.foreground_tab_first_paint = time_to_paint; } + + // Once first paint has been observed the entire to-paint tracking + // mechanism is no longer needed. + registrar_.Remove( + this, + content::NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE, + content::NotificationService::AllSources()); + + // Remove any tabs that have loaded. These were only being kept around + // while waiting for a paint event. + std::vector<NavigationController*> loaded_tabs; + for (auto& map_entry : tabs_tracked_) { + TabState& tab_state = map_entry.second; + if (tab_state.loading_state == TAB_IS_LOADED) + loaded_tabs.push_back(tab_state.controller); + } + for (auto& tab : loaded_tabs) + RemoveTab(tab); } break; } @@ -169,72 +261,69 @@ void SessionRestoreStatsCollector::Observe( break; } - // Check if we are done and if so, reset |this_retainer_| as the collector no - // longer needs to stay alive. - if ((got_first_paint_ || render_widget_hosts_to_paint_.empty()) && - tabs_tracked_.empty() && render_widget_hosts_loading_.empty()) - this_retainer_ = nullptr; -} - -void SessionRestoreStatsCollector::AddTabs( - const std::vector<SessionRestoreDelegate::RestoredTab>& tabs) { - tab_count_ += tabs.size(); - for (auto& tab : tabs) { - RegisterForNotifications(&tab.contents()->GetController()); - if (tab.is_active()) { - RenderWidgetHost* render_widget_host = - GetRenderWidgetHost(&tab.contents()->GetController()); - render_widget_hosts_loading_.insert(render_widget_host); - } - } + ReleaseIfDoneTracking(); } void SessionRestoreStatsCollector::RemoveTab(NavigationController* tab) { + // Stop observing this tab. registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, - content::Source<WebContents>(tab->GetWebContents())); + Source<WebContents>(tab->GetWebContents())); registrar_.Remove(this, content::NOTIFICATION_LOAD_STOP, - content::Source<NavigationController>(tab)); + Source<NavigationController>(tab)); registrar_.Remove(this, content::NOTIFICATION_LOAD_START, - content::Source<NavigationController>(tab)); - if (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); - - // 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. - if (tabs_tracked_.empty() && render_widget_hosts_loading_.empty()) { - 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. - std::string time_for_count = - base::StringPrintf("SessionRestore.AllTabsLoaded_%d", tab_count_); - base::HistogramBase* counter_for_count = base::Histogram::FactoryTimeGet( - time_for_count, base::TimeDelta::FromMilliseconds(10), - base::TimeDelta::FromSeconds(100), 100, - base::Histogram::kUmaTargetedHistogramFlag); - counter_for_count->AddTime(time_to_load); + Source<NavigationController>(tab)); - UMA_HISTOGRAM_COUNTS_100("SessionRestore.ParallelTabLoads", - max_parallel_tab_loads_); + auto tab_it = tabs_tracked_.find(tab); + DCHECK(tab_it != tabs_tracked_.end()); + TabState& tab_state = tab_it->second; + + // If this tab was waiting for a NOTIFICATION_LOAD_STOP event then update + // the loading counts. + if (tab_state.loading_state == TAB_IS_LOADING) { + DCHECK_LT(0u, loading_tab_count_); + --loading_tab_count_; + } + + // Only non-deferred not-loading/not-loaded tabs are waiting to be loaded. + if (tab_state.loading_state != TAB_IS_LOADED && !tab_state.is_deferred) { + DCHECK_LT(0u, waiting_for_load_tab_count_); + // It's possible for waiting_for_load_tab_count_ to reach zero here. This + // function is only called from 'Observe', so the transition will be + // noticed there. + --waiting_for_load_tab_count_; + } + + if (tab_state.is_deferred) + --deferred_tab_count_; + + // Remove the tab from the |tracked_tabs_| map. + tabs_tracked_.erase(tab_it); + + // It is possible for all restored contents to be destroyed or forcibly + // renavigated before a first paint has arrived. This can be detected by + // tabs_tracked_ containing only deferred tabs. At this point the paint + // mechanism can be disabled and stats collection will stop. + if (tabs_tracked_.size() == deferred_tab_count_ && !got_first_paint_) { + got_first_paint_ = true; + registrar_.Remove( + this, content::NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE, + content::NotificationService::AllSources()); } } -void SessionRestoreStatsCollector::RegisterForNotifications( +SessionRestoreStatsCollector::TabState* +SessionRestoreStatsCollector::RegisterForNotifications( NavigationController* tab) { registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, - content::Source<WebContents>(tab->GetWebContents())); + Source<WebContents>(tab->GetWebContents())); registrar_.Add(this, content::NOTIFICATION_LOAD_STOP, - content::Source<NavigationController>(tab)); + Source<NavigationController>(tab)); registrar_.Add(this, content::NOTIFICATION_LOAD_START, - content::Source<NavigationController>(tab)); - tabs_tracked_.insert(tab); + Source<NavigationController>(tab)); + auto result = tabs_tracked_.insert(std::make_pair(tab, TabState(tab))); + DCHECK(result.second); + TabState* tab_state = &result.first->second; + return tab_state; } RenderWidgetHost* SessionRestoreStatsCollector::GetRenderWidgetHost( @@ -249,6 +338,158 @@ RenderWidgetHost* SessionRestoreStatsCollector::GetRenderWidgetHost( return nullptr; } -// static -SessionRestoreStatsCollector* SessionRestoreStatsCollector::shared_collector_ = - nullptr; +SessionRestoreStatsCollector::TabState* +SessionRestoreStatsCollector::GetTabState(NavigationController* tab) { + // This lookup can fail because DeferTab calls can arrive for tabs that have + // already loaded (user forced) and are no longer tracked. + auto it = tabs_tracked_.find(tab); + if (it == tabs_tracked_.end()) + return nullptr; + return &it->second; +} + +SessionRestoreStatsCollector::TabState* +SessionRestoreStatsCollector::GetTabState(RenderWidgetHost* tab) { + for (auto& pair : tabs_tracked_) { + if (pair.second.render_widget_host == tab) + return &pair.second; + } + // It's possible for this lookup to fail as paint events can be received for + // tabs that aren't being tracked. + return nullptr; +} + +void SessionRestoreStatsCollector::MarkTabAsLoading(TabState* tab_state) { + // If the tab has already started or finished loading then a user navigation + // has caused the tab to be forcibly reloaded. This tab can be removed from + // observation. + if (tab_state->loading_state == TAB_IS_LOADED) { + RemoveTab(tab_state->controller); + return; + } + + DCHECK_EQ(TAB_IS_NOT_LOADING, tab_state->loading_state); + if (tab_state->loading_state != TAB_IS_NOT_LOADING) + return; + tab_state->loading_state = TAB_IS_LOADING; + ++loading_tab_count_; + + if (!done_tracking_non_deferred_tabs_) { + tab_loader_stats_.parallel_tab_loads = + std::max(tab_loader_stats_.parallel_tab_loads, loading_tab_count_); + } + + // Get the RenderWidgetHost for the tab and add it to the secondary index. + RenderWidgetHost* render_widget_host = + GetRenderWidgetHost(tab_state->controller); + DCHECK(render_widget_host); + tab_state->render_widget_host = render_widget_host; +} + +void SessionRestoreStatsCollector::ReleaseIfDoneTracking() { + // If non-deferred tabs are no longer being tracked then report tab loader + // statistics. + if (!done_tracking_non_deferred_tabs_ && got_first_paint_ && + waiting_for_load_tab_count_ == 0) { + done_tracking_non_deferred_tabs_ = true; + reporting_delegate_->ReportTabLoaderStats(tab_loader_stats_); + } + + // If tracking is completely finished then emit collected metrics and destroy + // this stats collector. + if (done_tracking_non_deferred_tabs_ && tabs_tracked_.empty()) + this_retainer_ = nullptr; +} + +SessionRestoreStatsCollector::UmaStatsReportingDelegate:: + UmaStatsReportingDelegate() + : got_report_tab_deferred_(false) { +} + +void SessionRestoreStatsCollector::UmaStatsReportingDelegate:: + ReportTabLoaderStats(const TabLoaderStats& tab_loader_stats) { + UMA_HISTOGRAM_COUNTS_100("SessionRestore.TabCount", + tab_loader_stats.tab_count); + + EmitUmaSessionRestoreActionEvent(SESSION_RESTORE_ACTIONS_UMA_INITIATED); + + for (size_t i = 0; i < tab_loader_stats.tab_count; ++i) { + EmitUmaSessionRestoreTabActionEvent( + SESSION_RESTORE_TAB_ACTIONS_UMA_TAB_CREATED); + } + + for (size_t i = 0; i < tab_loader_stats.tabs_loaded; ++i) { + EmitUmaSessionRestoreTabActionEvent( + SESSION_RESTORE_TAB_ACTIONS_UMA_TAB_LOADED); + } + + if (!tab_loader_stats.foreground_tab_first_loaded.is_zero()) { + UMA_HISTOGRAM_CUSTOM_TIMES("SessionRestore.ForegroundTabFirstLoaded", + tab_loader_stats.foreground_tab_first_loaded, + base::TimeDelta::FromMilliseconds(10), + base::TimeDelta::FromSeconds(100), 100); + + // Record a time for the number of tabs, to help track down contention. + std::string time_for_count = base::StringPrintf( + "SessionRestore.ForegroundTabFirstLoaded_%u", + static_cast<unsigned int>(tab_loader_stats.tab_count)); + base::HistogramBase* counter_for_count = base::Histogram::FactoryTimeGet( + time_for_count, base::TimeDelta::FromMilliseconds(10), + base::TimeDelta::FromSeconds(100), 100, + base::Histogram::kUmaTargetedHistogramFlag); + counter_for_count->AddTime(tab_loader_stats.foreground_tab_first_loaded); + } + + if (!tab_loader_stats.foreground_tab_first_paint.is_zero()) { + UMA_HISTOGRAM_CUSTOM_TIMES("SessionRestore.ForegroundTabFirstPaint3", + tab_loader_stats.foreground_tab_first_paint, + base::TimeDelta::FromMilliseconds(100), + base::TimeDelta::FromMinutes(16), 50); + + std::string time_for_count = base::StringPrintf( + "SessionRestore.ForegroundTabFirstPaint3_%u", + static_cast<unsigned int>(tab_loader_stats.tab_count)); + base::HistogramBase* counter_for_count = base::Histogram::FactoryTimeGet( + time_for_count, base::TimeDelta::FromMilliseconds(100), + base::TimeDelta::FromMinutes(16), 50, + base::Histogram::kUmaTargetedHistogramFlag); + counter_for_count->AddTime(tab_loader_stats.foreground_tab_first_paint); + } + + if (!tab_loader_stats.non_deferred_tabs_loaded.is_zero()) { + UMA_HISTOGRAM_CUSTOM_TIMES("SessionRestore.AllTabsLoaded", + tab_loader_stats.non_deferred_tabs_loaded, + base::TimeDelta::FromMilliseconds(10), + base::TimeDelta::FromSeconds(100), 100); + + // Record a time for the number of tabs, to help track down contention. + std::string time_for_count = base::StringPrintf( + "SessionRestore.AllTabsLoaded_%u", + static_cast<unsigned int>(tab_loader_stats.tab_count)); + base::HistogramBase* counter_for_count = base::Histogram::FactoryTimeGet( + time_for_count, base::TimeDelta::FromMilliseconds(10), + base::TimeDelta::FromSeconds(100), 100, + base::Histogram::kUmaTargetedHistogramFlag); + counter_for_count->AddTime(tab_loader_stats.non_deferred_tabs_loaded); + } + + UMA_HISTOGRAM_COUNTS_100("SessionRestore.ParallelTabLoads", + tab_loader_stats.parallel_tab_loads); +} + +void SessionRestoreStatsCollector::UmaStatsReportingDelegate:: + ReportTabDeferred() { + if (!got_report_tab_deferred_) { + got_report_tab_deferred_ = true; + EmitUmaSessionRestoreActionEvent(SESSION_RESTORE_ACTIONS_UMA_DEFERRED_TABS); + } + + EmitUmaSessionRestoreTabActionEvent( + SESSION_RESTORE_TAB_ACTIONS_UMA_TAB_LOADING_DEFERRED); +} + +void SessionRestoreStatsCollector::UmaStatsReportingDelegate:: + ReportDeferredTabLoaded() { + EmitUmaSessionRestoreTabActionEvent( + SESSION_RESTORE_TAB_ACTIONS_UMA_DEFERRED_TAB_LOADED); +} |