Bug 1021922 - Record telemetry for browser database operations. r=mfinkle, a=lmandel
authorRichard Newman <rnewman@mozilla.com>
Tue, 10 Jun 2014 10:45:11 -0700
changeset 208203 75979b9fa1f349c8010ed355b83acc0a515dc2b7
parent 208202 da411590e56d8a0f5d6f622af42726c56f813747
child 208204 beb8b71d7b9a8b83a05242ce0a1c807d8946aa63
push id494
push userraliiev@mozilla.com
push dateMon, 25 Aug 2014 18:42:16 +0000
treeherdermozilla-release@a3cc3e46b571 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmfinkle, lmandel
bugs1021922
milestone32.0a2
Bug 1021922 - Record telemetry for browser database operations. r=mfinkle, a=lmandel
mobile/android/base/GlobalHistory.java
mobile/android/base/home/SearchLoader.java
mobile/android/base/home/TopSitesPanel.java
toolkit/components/telemetry/Histograms.json
--- a/mobile/android/base/GlobalHistory.java
+++ b/mobile/android/base/GlobalHistory.java
@@ -1,33 +1,37 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko;
 
-import org.mozilla.gecko.db.BrowserDB;
-import org.mozilla.gecko.util.ThreadUtils;
-
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.Handler;
-import android.util.Log;
-
 import java.lang.ref.SoftReference;
 import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.Queue;
 import java.util.Set;
 
+import org.mozilla.gecko.db.BrowserDB;
+import org.mozilla.gecko.util.ThreadUtils;
+
+import android.database.Cursor;
+import android.os.Handler;
+import android.os.SystemClock;
+import android.util.Log;
+
 class GlobalHistory {
     private static final String LOGTAG = "GeckoGlobalHistory";
 
-    private static GlobalHistory sInstance = new GlobalHistory();
+    private static final String TELEMETRY_HISTOGRAM_ADD = "FENNEC_GLOBALHISTORY_ADD_MS";
+    private static final String TELEMETRY_HISTOGRAM_UPDATE = "FENNEC_GLOBALHISTORY_UPDATE_MS";
+    private static final String TELEMETRY_HISTOGRAM_BUILD_VISITED_LINK = "FENNEC_GLOBALHISTORY_VISITED_BUILD_MS";
+
+    private static final GlobalHistory sInstance = new GlobalHistory();
 
     static GlobalHistory getInstance() {
         return sInstance;
     }
 
     // this is the delay between receiving a URI check request and processing it.
     // this allows batching together multiple requests and processing them together,
     // which is more efficient.
@@ -43,45 +47,48 @@ class GlobalHistory {
         mHandler = ThreadUtils.getBackgroundHandler();
         mPendingUris = new LinkedList<String>();
         mVisitedCache = new SoftReference<Set<String>>(null);
         mNotifierRunnable = new Runnable() {
             @Override
             public void run() {
                 Set<String> visitedSet = mVisitedCache.get();
                 if (visitedSet == null) {
-                    // the cache was wiped away, repopulate it
+                    // The cache was wiped. Repopulate it.
                     Log.w(LOGTAG, "Rebuilding visited link set...");
-                    visitedSet = new HashSet<String>();
-                    Cursor c = null;
+                    final long start = SystemClock.uptimeMillis();
+                    final Cursor c = BrowserDB.getAllVisitedHistory(GeckoAppShell.getContext().getContentResolver());
+                    if (c == null) {
+                        return;
+                    }
+
                     try {
-                        c = BrowserDB.getAllVisitedHistory(GeckoAppShell.getContext().getContentResolver());
-                        if (c == null) {
-                            return;
-                        }
-
+                        visitedSet = new HashSet<String>();
                         if (c.moveToFirst()) {
                             do {
                                 visitedSet.add(c.getString(0));
                             } while (c.moveToNext());
                         }
                         mVisitedCache = new SoftReference<Set<String>>(visitedSet);
+                        final long end = SystemClock.uptimeMillis();
+                        final long took = end - start;
+                        Telemetry.HistogramAdd(TELEMETRY_HISTOGRAM_BUILD_VISITED_LINK, (int) Math.min(took, Integer.MAX_VALUE));
                     } finally {
-                        if (c != null)
-                            c.close();
+                        c.close();
                     }
                 }
 
-                // this runs on the same handler thread as the checkUriVisited code,
-                // so no synchronization needed
+                // This runs on the same handler thread as the checkUriVisited code,
+                // so no synchronization is needed.
                 while (true) {
-                    String uri = mPendingUris.poll();
+                    final String uri = mPendingUris.poll();
                     if (uri == null) {
                         break;
                     }
+
                     if (visitedSet.contains(uri)) {
                         GeckoAppShell.notifyUriVisited(uri);
                     }
                 }
                 mProcessing = false;
             }
         };
     }
@@ -90,22 +97,31 @@ class GlobalHistory {
         Set<String> visitedSet = mVisitedCache.get();
         if (visitedSet != null) {
             visitedSet.add(uri);
         }
         GeckoAppShell.notifyUriVisited(uri);
     }
 
     public void add(String uri) {
+        final long start = SystemClock.uptimeMillis();
         BrowserDB.updateVisitedHistory(GeckoAppShell.getContext().getContentResolver(), uri);
+        final long end = SystemClock.uptimeMillis();
+        final long took = end - start;
+        Telemetry.HistogramAdd(TELEMETRY_HISTOGRAM_ADD, (int) Math.min(took, Integer.MAX_VALUE));
         addToGeckoOnly(uri);
     }
 
+    @SuppressWarnings("static-method")
     public void update(String uri, String title) {
+        final long start = SystemClock.uptimeMillis();
         BrowserDB.updateHistoryTitle(GeckoAppShell.getContext().getContentResolver(), uri, title);
+        final long end = SystemClock.uptimeMillis();
+        final long took = end - start;
+        Telemetry.HistogramAdd(TELEMETRY_HISTOGRAM_UPDATE, (int) Math.min(took, Integer.MAX_VALUE));
     }
 
     public void checkUriVisited(final String uri) {
         mHandler.post(new Runnable() {
             @Override
             public void run() {
                 // this runs on the same handler thread as the processing loop,
                 // so no synchronization needed
--- a/mobile/android/base/home/SearchLoader.java
+++ b/mobile/android/base/home/SearchLoader.java
@@ -1,29 +1,33 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.home;
 
+import org.mozilla.gecko.Telemetry;
 import org.mozilla.gecko.db.BrowserDB;
 
 import android.content.Context;
 import android.database.Cursor;
 import android.os.Bundle;
+import android.os.SystemClock;
 import android.support.v4.app.LoaderManager;
 import android.support.v4.app.LoaderManager.LoaderCallbacks;
 import android.support.v4.content.Loader;
+import android.util.Log;
 
 /**
  * Encapsulates the implementation of the search cursor loader.
  */
 class SearchLoader {
-    // Key for search terms
+    public static final String LOGTAG = "GeckoSearchLoader";
+
     private static final String KEY_SEARCH_TERM = "search_term";
 
     private SearchLoader() {
     }
 
     public static Loader<Cursor> createInstance(Context context, Bundle args) {
         if (args != null) {
             final String searchTerm = args.getString(KEY_SEARCH_TERM);
@@ -48,30 +52,37 @@ class SearchLoader {
 
     public static void restart(LoaderManager manager, int loaderId,
                                LoaderCallbacks<Cursor> callbacks, String searchTerm) {
         final Bundle args = createArgs(searchTerm);
         manager.restartLoader(loaderId, args, callbacks);
     }
 
     public static class SearchCursorLoader extends SimpleCursorLoader {
+        private static final String TELEMETRY_HISTOGRAM_LOAD_CURSOR = "FENNEC_SEARCH_LOADER_TIME_MS";
+
         // Max number of search results
         private static final int SEARCH_LIMIT = 100;
 
         // The target search term associated with the loader
         private final String mSearchTerm;
 
         public SearchCursorLoader(Context context, String searchTerm) {
             super(context);
             mSearchTerm = searchTerm;
         }
 
         @Override
         public Cursor loadCursor() {
-            return BrowserDB.filter(getContext().getContentResolver(), mSearchTerm, SEARCH_LIMIT);
+            final long start = SystemClock.uptimeMillis();
+            final Cursor cursor = BrowserDB.filter(getContext().getContentResolver(), mSearchTerm, SEARCH_LIMIT);
+            final long end = SystemClock.uptimeMillis();
+            final long took = end - start;
+            Telemetry.HistogramAdd(TELEMETRY_HISTOGRAM_LOAD_CURSOR, (int) Math.min(took, Integer.MAX_VALUE));
+            return cursor;
         }
 
         public String getSearchTerm() {
             return mSearchTerm;
         }
     }
 
 }
--- a/mobile/android/base/home/TopSitesPanel.java
+++ b/mobile/android/base/home/TopSitesPanel.java
@@ -26,19 +26,19 @@ import org.mozilla.gecko.home.TopSitesGr
 import org.mozilla.gecko.util.ThreadUtils;
 
 import android.app.Activity;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.database.Cursor;
 import android.graphics.Bitmap;
-import android.graphics.Color;
 import android.net.Uri;
 import android.os.Bundle;
+import android.os.SystemClock;
 import android.support.v4.app.FragmentManager;
 import android.support.v4.app.LoaderManager.LoaderCallbacks;
 import android.support.v4.content.AsyncTaskLoader;
 import android.support.v4.content.Loader;
 import android.support.v4.widget.CursorAdapter;
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.ContextMenu;
@@ -425,29 +425,34 @@ public class TopSitesPanel extends HomeF
         }
 
         // Once thumbnails have finished loading, the UI is ready. Reset
         // Gecko to normal priority.
         ThreadUtils.resetGeckoPriority();
     }
 
     private static class TopSitesLoader extends SimpleCursorLoader {
-        // Max number of search results
+        // Max number of search results.
         private static final int SEARCH_LIMIT = 30;
+        private static final String TELEMETRY_HISTOGRAM_LOAD_CURSOR = "FENNEC_TOPSITES_LOADER_TIME_MS";
         private int mMaxGridEntries;
 
         public TopSitesLoader(Context context) {
             super(context);
             mMaxGridEntries = context.getResources().getInteger(R.integer.number_of_top_sites);
         }
 
         @Override
         public Cursor loadCursor() {
-            trace("TopSitesLoader.loadCursor()");
-            return BrowserDB.getTopSites(getContext().getContentResolver(), mMaxGridEntries, SEARCH_LIMIT);
+            final long start = SystemClock.uptimeMillis();
+            final Cursor cursor = BrowserDB.getTopSites(getContext().getContentResolver(), mMaxGridEntries, SEARCH_LIMIT);
+            final long end = SystemClock.uptimeMillis();
+            final long took = end - start;
+            Telemetry.HistogramAdd(TELEMETRY_HISTOGRAM_LOAD_CURSOR, (int) Math.min(took, Integer.MAX_VALUE));
+            return cursor;
         }
     }
 
     private class VisitedAdapter extends CursorAdapter {
         public VisitedAdapter(Context context, Cursor cursor) {
             super(context, cursor, 0);
         }
 
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -4276,46 +4276,71 @@
     "expires_in_version": "never",
     "kind": "exponential",
     "high": "1000000",
     "n_buckets": 20,
     "extended_statistics_ok": true,
     "description": "Number of history entries in the original XUL places database",
     "cpp_guard": "ANDROID"
   },
-  "FENNEC_AWESOMEBAR_ALLPAGES_EMPTY_TIME": {
+  "FENNEC_GLOBALHISTORY_ADD_MS": {
     "expires_in_version": "never",
     "kind": "exponential",
     "low": 10,
     "high": "20000",
     "n_buckets": 20,
-    "description": "Fennec: Time for the Awesomebar Top Sites query to return with no filter set (ms)",
+    "description": "Time for a record to be added to history (ms)",
+    "cpp_guard": "ANDROID"
+  },
+  "FENNEC_GLOBALHISTORY_UPDATE_MS": {
+    "expires_in_version": "never",
+    "kind": "exponential",
+    "low": 10,
+    "high": "20000",
+    "n_buckets": 20,
+    "description": "Time for a record to be updated in history (ms)",
+    "cpp_guard": "ANDROID"
+  },
+  "FENNEC_GLOBALHISTORY_VISITED_BUILD_MS": {
+    "expires_in_version": "never",
+    "kind": "exponential",
+    "low": 10,
+    "high": "20000",
+    "n_buckets": 20,
+    "description": "Time to update the visited link set (ms)",
     "cpp_guard": "ANDROID"
   },
   "FENNEC_LOWMEM_TAB_COUNT": {
     "expires_in_version": "never",
     "kind": "exponential",
     "high": 100,
     "n_buckets": 30,
     "description": "How many tabs were open when a low-memory event was received",
     "cpp_guard": "ANDROID"
   },
   "FENNEC_RESTORING_ACTIVITY": {
     "expires_in_version": "never",
     "kind": "flag",
     "description": "Fennec is starting up but the Gecko thread was still running",
     "cpp_guard": "ANDROID"
   },
-  "FENNEC_STARTUP_TIME_JAVAUI": {
-    "expires_in_version": "never",
-    "kind": "exponential",
-    "low": 100,
-    "high": "5000",
+  "FENNEC_SEARCH_LOADER_TIME_MS": {
+    "expires_in_version": "never",
+    "kind": "exponential",
+    "low": 10,
+    "high": "20000",
     "n_buckets": 20,
-    "description": "Time for the Java UI to load (ms)",
+    "description": "Time for a URL bar DB search to return (ms)",
+    "cpp_guard": "ANDROID"
+  },
+  "FENNEC_STARTUP_GECKOAPP_ACTION": {
+    "expires_in_version": "never",
+    "kind": "enumerated",
+    "n_values": 4,
+    "description": "The way the GeckoApp was launched. (Normal, URL, Prefetch, Redirector)",
     "cpp_guard": "ANDROID"
   },
   "FENNEC_STARTUP_TIME_ABOUTHOME": {
     "expires_in_version": "never",
     "kind": "exponential",
     "low": 100,
     "high": "10000",
     "n_buckets": 20,
@@ -4326,21 +4351,23 @@
     "expires_in_version": "never",
     "kind": "exponential",
     "low": 500,
     "high": "20000",
     "n_buckets": 20,
     "description": "Time for the Gecko:Ready message to arrive (ms)",
     "cpp_guard": "ANDROID"
   },
-  "FENNEC_STARTUP_GECKOAPP_ACTION": {
-    "expires_in_version": "never",
-    "kind": "enumerated",
-    "n_values": 4,
-    "description": "The way the GeckoApp was launched. (Normal, URL, Prefetch, Redirector)",
+  "FENNEC_STARTUP_TIME_JAVAUI": {
+    "expires_in_version": "never",
+    "kind": "exponential",
+    "low": 100,
+    "high": "5000",
+    "n_buckets": 20,
+    "description": "Time for the Java UI to load (ms)",
     "cpp_guard": "ANDROID"
   },
   "FENNEC_TAB_EXPIRED": {
     "expires_in_version": "never",
     "kind": "exponential",
     "low": 10,
     "high": 604800,
     "n_buckets": 20,
@@ -4353,16 +4380,25 @@
     "kind": "exponential",
     "low": 10,
     "high": 604800,
     "n_buckets": 20,
     "extended_statistics_ok": true,
     "description": "How long (in seconds) a tab was inactive when it was OOM-zombified",
     "cpp_guard": "ANDROID"
   },
+  "FENNEC_TOPSITES_LOADER_TIME_MS": {
+    "expires_in_version": "never",
+    "kind": "exponential",
+    "low": 10,
+    "high": "20000",
+    "n_buckets": 20,
+    "description": "Time for the home screen Top Sites query to return with no filter set (ms)",
+    "cpp_guard": "ANDROID"
+  },
   "FENNEC_WAS_KILLED": {
     "expires_in_version": "never",
     "kind": "flag",
     "description": "Killed, likely due to an OOM condition",
     "cpp_guard": "ANDROID"
   },
   "SECURITY_UI": {
     "expires_in_version": "never",