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

Unified Diff: chrome/android/java/src/org/chromium/chrome/browser/TabUma.java

Issue 1032513003: Upstream TabUma. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: dtrainor's comments Created 5 years, 9 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/android/java/src/org/chromium/chrome/browser/TabUma.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/TabUma.java b/chrome/android/java/src/org/chromium/chrome/browser/TabUma.java
new file mode 100644
index 0000000000000000000000000000000000000000..0f4db8309dc6b50ce5bfa02c24f7c3d0d04ddfbc
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/TabUma.java
@@ -0,0 +1,257 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser;
+
+import android.os.SystemClock;
+
+import org.chromium.base.metrics.RecordHistogram;
+import org.chromium.chrome.browser.tabmodel.TabModel;
+import org.chromium.chrome.browser.tabmodel.TabModel.TabSelectionType;
+import org.chromium.net.NetError;
+
+/**
+ * Centralizes UMA data collection for Tab management.
+ * This will drive our memory optimization efforts, specially tab restoring and
+ * eviction.
+ * All calls must be made from the UI thread.
+ */
+public class TabUma {
+ // TabStatus defined in tools/metrics/histograms/histograms.xml.
+ static final int TAB_STATUS_MEMORY_RESIDENT = 0;
+ static final int TAB_STATUS_RELOAD_EVICTED = 1;
+ static final int TAB_STATUS_RELOAD_COLD_START_FG = 6;
+ static final int TAB_STATUS_RELOAD_COLD_START_BG = 7;
+ static final int TAB_STATUS_LAZY_LOAD_FOR_BG_TAB = 8;
+ static final int TAB_STATUS_LIM = 9;
+
+ // TabBackgroundLoadStatus defined in tools/metrics/histograms/histograms.xml.
+ static final int TAB_BACKGROUND_LOAD_SHOWN = 0;
+ static final int TAB_BACKGROUND_LOAD_LOST = 1;
+ static final int TAB_BACKGROUND_LOAD_SKIPPED = 2;
+ static final int TAB_BACKGROUND_LOAD_LIM = 3;
+
+ // The enum values for the Tab.RestoreResult histogram. The unusual order is to
+ // keep compatibility with the previous instance of the histogram that was using
+ // a boolean.
+ //
+ // Defined in tools/metrics/histograms/histograms.xml.
+ private static final int TAB_RESTORE_RESULT_FAILURE_OTHER = 0;
+ private static final int TAB_RESTORE_RESULT_SUCCESS = 1;
+ private static final int TAB_RESTORE_RESULT_FAILURE_NETWORK_CONNECTIVITY = 2;
+ private static final int TAB_RESTORE_RESULT_COUNT = 3;
+
+ // Counter of tab shows (as per onShow()) for all tabs.
+ private static long sAllTabsShowCount = 0;
+
+ private final Tab mTab;
+ private final TabModel mTabModel;
+
+ /**
+ * State in which the tab was created. This can be used in metric accounting - e.g. to
+ * distinguish reasons for a tab to be restored upon first display.
+ */
+ public enum TabCreationState {
+ LIVE_IN_FOREGROUND,
+ LIVE_IN_BACKGROUND,
+ FROZEN_ON_RESTORE,
+ FROZEN_FOR_LAZY_LOAD
+ }
+
+ private final TabCreationState mTabCreationState;
+
+ // Timestamp when this tab was last shown.
+ private long mLastShowMillis = -1;
+
+ // Timestamp of the beginning of the current tab restore.
+ private long mRestoreStartedAtMillis = -1;
+
+ /**
+ * Constructs a new UMA tracker for a specific tab.
+ * @param tab The tab whose metrics we want to track.
+ * @param creationState In what state the tab was created.
+ * @param model The tab model that contains this tab.
+ */
+ public TabUma(Tab tab, TabCreationState creationState, TabModel model) {
+ mTab = tab;
+ mTabCreationState = creationState;
+ mTabModel = model;
+ }
+
+ /**
+ * Records the tab restore result into several UMA histograms.
+ * @param succeeded Whether or not the tab restore succeeded.
+ * @param time The time taken to perform the tab restore.
+ * @param perceivedTime The perceived time taken to perform the tab restore.
+ * @param errorCode The error code, on failure (as denoted by the |succeeded| parameter).
+ */
+ void recordTabRestoreResult(boolean succeeded, long time, long perceivedTime, int errorCode) {
+ if (succeeded) {
+ RecordHistogram.recordEnumeratedHistogram(
+ "Tab.RestoreResult", TAB_RESTORE_RESULT_SUCCESS, TAB_RESTORE_RESULT_COUNT);
+ RecordHistogram.recordCountHistogram("Tab.RestoreTime", (int) time);
+ RecordHistogram.recordCountHistogram("Tab.PerceivedRestoreTime", (int) perceivedTime);
+ } else {
+ switch (errorCode) {
+ case NetError.ERR_INTERNET_DISCONNECTED:
+ case NetError.ERR_NAME_RESOLUTION_FAILED:
+ case NetError.ERR_DNS_TIMED_OUT:
+ RecordHistogram.recordEnumeratedHistogram("Tab.RestoreResult",
+ TAB_RESTORE_RESULT_FAILURE_NETWORK_CONNECTIVITY,
+ TAB_RESTORE_RESULT_COUNT);
+ break;
+ default:
+ RecordHistogram.recordEnumeratedHistogram("Tab.RestoreResult",
+ TAB_RESTORE_RESULT_FAILURE_OTHER, TAB_RESTORE_RESULT_COUNT);
+ }
+ }
+ }
+
+ /**
+ * Called upon tab display.
+ * @param selectionType determines how the tab was being shown
+ * @param previousTimestampMillis time of the previous display or creation time for the tabs
+ * opened in background and not yet displayed
+ */
+ void onShow(TabSelectionType selectionType, long previousTimestampMillis) {
+ long now = SystemClock.elapsedRealtime();
+ // Do not collect the tab switching data for the first switch to a tab after the cold start
+ // and for the tab switches that were not user-originated (e.g. the user closes the last
+ // incognito tab and the current normal mode tab is shown).
+ if (mLastShowMillis != -1 && selectionType == TabSelectionType.FROM_USER) {
+ long age = now - mLastShowMillis;
+ int rank = computeMRURank(mTab, mTabModel);
+ RecordHistogram.recordCountHistogram("Tab.SwitchedToForegroundAge", (int) age);
+ RecordHistogram.recordCountHistogram("Tab.SwitchedToForegroundMRURank", rank);
+ }
+
+ increaseTabShowCount();
+ boolean isOnBrowserStartup = sAllTabsShowCount == 1;
+ boolean performsLazyLoad =
+ mTabCreationState == TabCreationState.FROZEN_FOR_LAZY_LOAD && mLastShowMillis == -1;
+
+ int status;
+ if (mRestoreStartedAtMillis == -1 && !performsLazyLoad) {
+ // The tab is *not* being restored or loaded lazily on first display.
+ status = TAB_STATUS_MEMORY_RESIDENT;
+ } else if (mLastShowMillis == -1) {
+ // This is first display and the tab is being restored or loaded lazily.
+ if (isOnBrowserStartup) {
+ status = TAB_STATUS_RELOAD_COLD_START_FG;
+ } else if (mTabCreationState == TabCreationState.FROZEN_ON_RESTORE) {
+ status = TAB_STATUS_RELOAD_COLD_START_BG;
+ } else if (mTabCreationState == TabCreationState.FROZEN_FOR_LAZY_LOAD) {
+ status = TAB_STATUS_LAZY_LOAD_FOR_BG_TAB;
+ } else {
+ assert mTabCreationState == TabCreationState.LIVE_IN_FOREGROUND
+ || mTabCreationState == TabCreationState.LIVE_IN_BACKGROUND;
+ status = TAB_STATUS_RELOAD_EVICTED;
+ }
+ } else {
+ // The tab is being restored and this is *not* the first time the tab is shown.
+ status = TAB_STATUS_RELOAD_EVICTED;
+ }
+
+ // Record only user-visible switches to existing tabs. Do not record displays of newly
+ // created tabs (FROM_NEW) or selections of the previous tab that happen when we close the
+ // tab opened from intent while exiting Chrome (FROM_CLOSE).
+ if (selectionType == TabSelectionType.FROM_USER) {
+ RecordHistogram.recordEnumeratedHistogram(
+ "Tab.StatusWhenSwitchedBackToForeground", status, TAB_STATUS_LIM);
+ }
+
+ // Record Tab.BackgroundLoadStatus.
+ if (mLastShowMillis == -1) {
+ if (mTabCreationState == TabCreationState.LIVE_IN_BACKGROUND) {
+ if (mRestoreStartedAtMillis == -1) {
+ RecordHistogram.recordEnumeratedHistogram("Tab.BackgroundLoadStatus",
+ TAB_BACKGROUND_LOAD_SHOWN, TAB_BACKGROUND_LOAD_LIM);
+ } else {
+ RecordHistogram.recordEnumeratedHistogram("Tab.BackgroundLoadStatus",
+ TAB_BACKGROUND_LOAD_LOST, TAB_BACKGROUND_LOAD_LIM);
+ }
+ } else if (mTabCreationState == TabCreationState.FROZEN_FOR_LAZY_LOAD) {
+ assert mRestoreStartedAtMillis == -1;
+ RecordHistogram.recordEnumeratedHistogram("Tab.BackgroundLoadStatus",
+ TAB_BACKGROUND_LOAD_SKIPPED, TAB_BACKGROUND_LOAD_LIM);
+ }
+ }
+
+ // Record "tab age upon first display" metrics. previousTimestampMillis is persisted through
+ // cold starts.
+ if (mLastShowMillis == -1 && previousTimestampMillis > 0) {
+ if (isOnBrowserStartup) {
+ RecordHistogram.recordCountHistogram("Tabs.ForegroundTabAgeAtStartup",
+ (int) millisecondsToMinutes(System.currentTimeMillis()
+ - previousTimestampMillis));
+ } else if (selectionType == TabSelectionType.FROM_USER) {
+ RecordHistogram.recordCountHistogram("Tab.AgeUponRestoreFromColdStart",
+ (int) millisecondsToMinutes(System.currentTimeMillis()
+ - previousTimestampMillis));
+ }
+ }
+
+ mLastShowMillis = now;
+ }
+
+ /** Called when restore of the corresponding tab is triggered. */
+ void onRestoreStarted() {
+ mRestoreStartedAtMillis = SystemClock.elapsedRealtime();
+ }
+
+ /** Called when the correspoding tab completes a page load. */
+ void onLoadFinished() {
+ // Record only tab restores that the user became aware of. If the restore is triggered
+ // speculatively and completes before the user switches to the tab, then this case is
+ // reflected in Tab.StatusWhenSwitchedBackToForeground metric.
+ if (mRestoreStartedAtMillis != -1 && mLastShowMillis >= mRestoreStartedAtMillis) {
+ long now = SystemClock.elapsedRealtime();
+ long restoreTime = now - mRestoreStartedAtMillis;
+ long perceivedRestoreTime = now - mLastShowMillis;
+ recordTabRestoreResult(true, restoreTime, perceivedRestoreTime, -1);
+ }
+ mRestoreStartedAtMillis = -1;
+ }
+
+ /** Called when the correspoding tab fails a page load. */
+ void onLoadFailed(int errorCode) {
+ if (mRestoreStartedAtMillis != -1 && mLastShowMillis >= mRestoreStartedAtMillis) {
+ // Load time is ignored for failed loads.
+ recordTabRestoreResult(false, -1, -1, errorCode);
+ }
+ mRestoreStartedAtMillis = -1;
+ }
+
+ /** Called when the renderer of the correspoding tab crashes. */
+ void onRendererCrashed() {
+ if (mRestoreStartedAtMillis != -1) {
+ // TODO(ppi): Add a bucket in Tab.RestoreResult for restores failed due to
+ // renderer crashes and start to track that.
+ mRestoreStartedAtMillis = -1;
+ }
+ }
+
+ private static void increaseTabShowCount() {
+ sAllTabsShowCount++;
+ }
+
+ private static long millisecondsToMinutes(long msec) {
+ return msec / 1000 / 60;
+ }
+
+ /**
+ * @return The most recently used rank for this tab in [0 .. tabs.length - 1].
+ */
+ private static int computeMRURank(Tab tab, TabModel model) {
+ final long tabLastShow = tab.getTabUma().mLastShowMillis;
+ int mruRank = 0;
+ for (int i = 0; i < model.getCount(); i++) {
+ Tab otherTab = model.getTabAt(i);
+ if (otherTab != tab && otherTab.getTabUma().mLastShowMillis > tabLastShow) {
+ mruRank++;
+ }
+ }
+ return mruRank;
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698