Chromium Code Reviews| 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 f892d1ad107b4bdbb27b03cb5d161c475de593a2..34b3781d42be5caad6ce320934fb6b105c247441 100644 |
| --- a/chrome/browser/sessions/session_restore_stats_collector.cc |
| +++ b/chrome/browser/sessions/session_restore_stats_collector.cc |
| @@ -13,53 +13,117 @@ |
| #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); |
| +const char kSessionRestoreActions[] = "SessionRestore.Actions"; |
| - shared_collector_->AddTabs(tabs); |
| -} |
| +// 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, |
| +}; |
| -// 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); |
| +} // 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), |
| + : got_done_tracking_non_deferred_tabs_(false), |
| + got_first_foreground_load_(false), |
| got_first_paint_(false), |
| + got_report_tab_deferred_(false), |
| restore_started_(restore_started), |
| - tab_count_(0), |
| - max_parallel_tab_loads_(0) { |
| + waiting_for_load_tab_count_(0u), |
| + loading_tab_count_(0u) { |
| 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; |
| + // The collector should only be destroyed when tracking is entirely |
|
sky
2015/05/27 15:18:39
Is this true if shutdown happens before everything
chrisha
2015/06/03 21:16:36
Very good point. Removed.
|
| + // finished. |
| + DCHECK(DoneTracking()); |
| +} |
| + |
| +void SessionRestoreStatsCollector::TrackTabs( |
| + const std::vector<SessionRestoreDelegate::RestoredTab>& tabs) { |
| + DCHECK(!got_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 (auto& tab : tabs) { |
| + TabState* tab_state = RegisterForNotifications( |
| + &tab.contents()->GetController()); |
| + // Active tabs have already started loading, kicked by the TabLoader. |
|
sky
2015/05/27 15:18:39
Actually, don't they start loading because they ar
chrisha
2015/06/03 21:16:36
Acknowledged.
|
| + 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; |
| + |
| + // 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) |
| + --waiting_for_load_tab_count_; |
|
sky
2015/05/27 15:18:39
Might waiting_for_load_tab_count_ be 0 now?
chrisha
2015/06/03 21:16:36
Yeah, it might. I thought it simpler to keep all o
sky
2015/06/03 22:00:07
Helper function SGTM.
chrisha
2015/06/04 14:04:47
Done.
|
| + |
| + ReportTabDeferred(); |
| } |
| void SessionRestoreStatsCollector::Observe( |
| @@ -68,99 +132,110 @@ 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(); |
|
sky
2015/05/27 15:18:39
Code seems to assume we'll get a LOAD_STOP before
chrisha
2015/06/03 21:16:36
Another great catch.
I'm not sure if that's guara
|
| + 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; |
| + --loading_tab_count_; |
| + if (!tab_state->is_deferred) |
| + --waiting_for_load_tab_count_; |
| + |
| + // Update statistics. |
|
sky
2015/05/27 15:18:39
nit: this comment isn't really useful, I would nuk
chrisha
2015/06/03 21:16:36
Done.
|
| + if (tab_state->is_deferred) { |
| + ReportDeferredTabLoaded(); |
| + } else { |
| + DCHECK(!got_done_tracking_non_deferred_tabs_); |
| + ++tab_loader_stats_.tabs_loaded; |
| + } |
| + |
| + // Update UMA stats for foreground tabs. |
| + 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(!got_done_tracking_non_deferred_tabs_); |
| + tab_loader_stats_.foreground_tab_first_loaded = time_to_load; |
| } |
| + |
| + // If first paint has already been observed then there's no need to keep |
|
sky
2015/05/27 15:18:39
This comment explains what the code does not why.
chrisha
2015/06/03 21:16:36
Done.
|
| + // tracking this tab. |
| + 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(); |
| - if (!got_first_paint_ && render_widget_host->GetView() && |
| + 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. |
| + 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. |
| 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 |
| + DCHECK(!got_done_tracking_non_deferred_tabs_); |
| + tab_loader_stats_.foreground_tab_first_paint = time_to_paint; |
| + } else { |
| + // If this is a host for a tab we're not tracking then some other tab |
| // has rendered and there's no point tracking the time. This could |
| // happen because the user opened a different tab or restored tabs |
| - // to an already existing browser and an existing tab painted. |
| + // to an already existing browser and an existing tab was in the |
| + // foreground. |
| got_first_paint_ = true; |
|
sky
2015/05/27 15:18:39
AFAICT both paths set got_first_paint_ to true. Se
chrisha
2015/06/03 21:16:36
Indeed... remnant of the previous more tortured lo
|
| } |
| + |
| + if (got_first_paint_) { |
| + // If the 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 +244,59 @@ 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; |
| -} |
| + // If non-deferred tabs are no longer being tracked then detach this collector |
| + // from being the shared collector. |
| + if (!got_done_tracking_non_deferred_tabs_ && DoneTrackingNonDeferredTabs()) { |
| + got_done_tracking_non_deferred_tabs_ = true; |
| -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); |
| - } |
| + // Mark the point at which all tabs have loaded and log the UMA metrics. |
|
sky
2015/05/27 15:18:39
Again, not a useful comment.
chrisha
2015/06/03 21:16:36
Acknowledged.
|
| + tab_loader_stats_.all_tabs_loaded = |
| + base::TimeTicks::Now() - restore_started_; |
| + ReportTabLoaderStats(); |
| } |
| + |
| + // If tracking is completely finished then emit collected metrics and destroy |
| + // this stats collector. |
| + if (got_done_tracking_non_deferred_tabs_ && DoneTracking()) |
| + this_retainer_ = nullptr; |
| } |
| 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_); |
| - } |
| + // Get the tab state. |
|
sky
2015/05/27 15:18:39
Again, this comment isn't useful. It just document
chrisha
2015/06/03 21:16:36
Acknowledged.
|
| + auto tab_it = tabs_tracked_.find(tab); |
| + DCHECK(tab_it != tabs_tracked_.end()); |
| + TabState& tab_state = tab_it->second; |
| + |
| + // Remove the tab from the secondary index if it's there. |
| + auto rwh_it = render_widget_map_.find(tab_state.render_widget_host); |
| + if (rwh_it != render_widget_map_.end()) |
| + render_widget_map_.erase(rwh_it); |
| + |
| + // Remove the tab from the |tracked_tabs_| map. |
| + tabs_tracked_.erase(tab_it); |
| } |
| -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 +311,154 @@ 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) { |
| + // This lookup can fail as events are received for tabs that aren't |
|
sky
2015/05/27 15:18:39
You can figure out the NavigationController the RW
chrisha
2015/06/03 21:16:36
Done.
|
| + // explicitly being tracked. |
| + auto it = render_widget_map_.find(tab); |
| + if (it == render_widget_map_.end()) |
| + return nullptr; |
| + return it->second; |
| +} |
| + |
| +void SessionRestoreStatsCollector::MarkTabAsLoading(TabState* tab_state) { |
| + CHECK(tab_state->loading_state == TAB_IS_NOT_LOADING); |
|
sky
2015/05/27 15:18:39
Why the CHECK?
chrisha
2015/06/03 21:16:36
Made a DCHECK. This really shouldn't be called twi
|
| + if (tab_state->loading_state != TAB_IS_NOT_LOADING) |
| + return; |
| + tab_state->loading_state = TAB_IS_LOADING; |
| + ++loading_tab_count_; |
| + |
| + DCHECK(!got_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; |
| + auto result = render_widget_map_.insert(std::make_pair( |
| + render_widget_host, tab_state)); |
| + DCHECK(result.second); |
| +} |
| + |
| +bool SessionRestoreStatsCollector::DoneTrackingNonDeferredTabs() const { |
| + // This should only be called when it hasn't yet returned true. |
| + DCHECK(!got_done_tracking_non_deferred_tabs_); |
| + return got_first_paint_ && waiting_for_load_tab_count_ == 0; |
| +} |
| + |
| +bool SessionRestoreStatsCollector::DoneTracking() const { |
| + // This should only be called once DoneTrackingNonDeferredTabs has returned |
| + // true. |
| + DCHECK(got_done_tracking_non_deferred_tabs_); |
| + return tabs_tracked_.empty() && render_widget_map_.empty(); |
| +} |
| + |
| +void SessionRestoreStatsCollector::ReportTabLoaderStats() { |
| + UMA_HISTOGRAM_COUNTS_100("SessionRestore.TabCount", |
| + tab_loader_stats_.tab_count); |
| + |
| + UMA_HISTOGRAM_ENUMERATION(kSessionRestoreActions, |
| + SESSION_RESTORE_ACTIONS_UMA_INITIATED, |
| + SESSION_RESTORE_ACTIONS_UMA_MAX); |
| + |
| + for (size_t i = 0; i < tab_loader_stats_.tab_count; ++i) { |
| + UMA_HISTOGRAM_ENUMERATION("SessionRestore.TabActions", |
| + SESSION_RESTORE_TAB_ACTIONS_UMA_TAB_CREATED, |
| + SESSION_RESTORE_TAB_ACTIONS_UMA_MAX); |
| + } |
| + |
| + for (size_t i = 0; i < tab_loader_stats_.tabs_loaded; ++i) { |
| + UMA_HISTOGRAM_ENUMERATION("SessionRestore.TabActions", |
| + SESSION_RESTORE_TAB_ACTIONS_UMA_TAB_LOADED, |
| + SESSION_RESTORE_TAB_ACTIONS_UMA_MAX); |
| + } |
| + |
| + 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_%d", |
| + 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_%d", |
| + 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_.all_tabs_loaded.is_zero()) { |
| + UMA_HISTOGRAM_CUSTOM_TIMES("SessionRestore.AllTabsLoaded", |
| + tab_loader_stats_.all_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_%d", |
| + 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_.all_tabs_loaded); |
| + } |
| + |
| + UMA_HISTOGRAM_COUNTS_100("SessionRestore.ParallelTabLoads", |
| + tab_loader_stats_.parallel_tab_loads); |
| +} |
| + |
| +void SessionRestoreStatsCollector::ReportTabDeferred() { |
| + if (!got_report_tab_deferred_) { |
| + got_report_tab_deferred_ = true; |
| + |
| + UMA_HISTOGRAM_ENUMERATION(kSessionRestoreActions, |
| + SESSION_RESTORE_ACTIONS_UMA_DEFERRED_TABS, |
| + SESSION_RESTORE_ACTIONS_UMA_MAX); |
| + } |
| + |
| + UMA_HISTOGRAM_ENUMERATION( |
| + "SessionRestore.TabActions", |
| + SESSION_RESTORE_TAB_ACTIONS_UMA_TAB_LOADING_DEFERRED, |
| + SESSION_RESTORE_TAB_ACTIONS_UMA_MAX); |
| +} |
| + |
| +void SessionRestoreStatsCollector::ReportDeferredTabLoaded() { |
| + UMA_HISTOGRAM_ENUMERATION( |
| + "SessionRestore.TabActions", |
| + SESSION_RESTORE_TAB_ACTIONS_UMA_DEFERRED_TAB_LOADED, |
| + SESSION_RESTORE_TAB_ACTIONS_UMA_MAX); |
| +} |