Bug 1075644 - Reduce Gecko thread priority at very start; r=snorp r=bnicholson
☠☠ backed out by 8f1758ce53f0 ☠ ☠
authorJim Chen <nchen@mozilla.com>
Mon, 06 Oct 2014 13:23:53 -0400
changeset 209056 4fee6e1f1ad29c5a711ce3ab521b17fdd1539e49
parent 209055 f5db0dae14347be0f0c6c266e08ba8600f9714e8
child 209057 c5c3dbaf007e60c43daf651ec21270c1bc86ffc4
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewerssnorp, bnicholson
bugs1075644
milestone35.0a1
Bug 1075644 - Reduce Gecko thread priority at very start; r=snorp r=bnicholson
mobile/android/base/GeckoApp.java
mobile/android/base/GeckoThread.java
mobile/android/base/home/TopSitesPanel.java
mobile/android/base/util/ThreadUtils.java
--- a/mobile/android/base/GeckoApp.java
+++ b/mobile/android/base/GeckoApp.java
@@ -1224,16 +1224,21 @@ public abstract class GeckoApp
                 @Override
                 public void run() {
                     GeckoThread.setLaunchState(GeckoThread.LaunchState.Launched);
                     GeckoThread.createAndStart();
                 }
             }, 1000 * 5 /* 5 seconds */);
         }
 
+        // Heavy load on the Gecko thread can slow down the time it takes for UI to appear on
+        // single-core devices. By minimizing the Gecko thread priority, we ensure that the UI
+        // appears quickly. The priority is reset to normal once thumbnails are loaded.
+        ThreadUtils.reduceGeckoPriority();
+
         MemoryMonitor.getInstance().init(getApplicationContext());
 
         Tabs.getInstance().attachToContext(this);
         try {
             Favicons.initializeWithContext(this);
         } catch (Exception e) {
             Log.e(LOGTAG, "Exception starting favicon cache. Corrupt resources?", e);
         }
@@ -1600,16 +1605,20 @@ public abstract class GeckoApp
             GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Viewport:Flush", null));
         }
 
         if (ACTION_ALERT_CALLBACK.equals(action)) {
             processAlertCallback(intent);
         } else if (NotificationHelper.HELPER_BROADCAST_ACTION.equals(action)) {
             NotificationHelper.getInstance(getApplicationContext()).handleNotificationIntent(intent);
         }
+
+        // Reset Gecko to normal priority. We may reduce the
+        // priority again later, e.g. for loading thumbnails.
+        ThreadUtils.resetGeckoPriority();
     }
 
     private String restoreSessionTabs(final boolean isExternalURL) throws SessionRestoreException {
         try {
             String sessionString = getProfile().readSessionFile(false);
             if (sessionString == null) {
                 throw new SessionRestoreException("Could not read from session file");
             }
--- a/mobile/android/base/GeckoThread.java
+++ b/mobile/android/base/GeckoThread.java
@@ -46,16 +46,17 @@ public class GeckoThread extends Thread 
     private final String mAction;
     private final String mUri;
 
     public static boolean ensureInit() {
         ThreadUtils.assertOnUiThread();
         if (isCreated())
             return false;
         sGeckoThread = new GeckoThread(sArgs, sAction, sUri);
+        ThreadUtils.sGeckoThread = sGeckoThread;
         return true;
     }
 
     public static String sArgs;
     public static String sAction;
     public static String sUri;
 
     public static void setArgs(String args) {
@@ -159,17 +160,16 @@ public class GeckoThread extends Thread 
         }
 
         return (args != null ? args : "") + profileArg + guestArg;
     }
 
     @Override
     public void run() {
         Looper.prepare();
-        ThreadUtils.sGeckoThread = this;
         ThreadUtils.sGeckoHandler = new Handler();
         ThreadUtils.sGeckoQueue = Looper.myQueue();
 
         String path = initGeckoEnvironment();
 
         // This can only happen after the call to initGeckoEnvironment
         // above, because otherwise the JNI code hasn't been loaded yet.
         ThreadUtils.postToUiThread(new Runnable() {
--- a/mobile/android/base/home/TopSitesPanel.java
+++ b/mobile/android/base/home/TopSitesPanel.java
@@ -93,19 +93,16 @@ public class TopSitesPanel extends HomeF
     private ThumbnailsLoaderCallbacks mThumbnailsLoaderCallbacks;
 
     // Listener for editing pinned sites.
     private EditPinnedSiteListener mEditPinnedSiteListener;
 
     // Max number of entries shown in the grid from the cursor.
     private int mMaxGridEntries;
 
-    // Time in ms until the Gecko thread is reset to normal priority.
-    private static final long PRIORITY_RESET_TIMEOUT = 10000;
-
     public static TopSitesPanel newInstance() {
         return new TopSitesPanel();
     }
 
     private static boolean logDebug = Log.isLoggable(LOGTAG, Log.DEBUG);
     private static boolean logVerbose = Log.isLoggable(LOGTAG, Log.VERBOSE);
 
     private static void debug(final String message) {
@@ -342,17 +339,17 @@ public class TopSitesPanel extends HomeF
         getLoaderManager().initLoader(LOADER_ID_TOP_SITES, null, mCursorLoaderCallbacks);
 
         // Since this is the primary fragment that loads whenever about:home is
         // visited, we want to load it as quickly as possible. Heavy load on
         // the Gecko thread can slow down the time it takes for thumbnails to
         // appear, especially during startup (bug 897162). By minimizing the
         // Gecko thread priority, we ensure that the UI appears quickly. The
         // priority is reset to normal once thumbnails are loaded.
-        ThreadUtils.reduceGeckoPriority(PRIORITY_RESET_TIMEOUT);
+        ThreadUtils.reduceGeckoPriority();
     }
 
     /**
      * Listener for editing pinned sites.
      */
     private class EditPinnedSiteListener implements OnEditPinnedSiteListener,
                                                     OnSiteSelectedListener {
         // Tag for the PinSiteDialog fragment.
--- a/mobile/android/base/util/ThreadUtils.java
+++ b/mobile/android/base/util/ThreadUtils.java
@@ -12,16 +12,19 @@ import java.util.Map;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.MessageQueue;
 import android.util.Log;
 
 public final class ThreadUtils {
     private static final String LOGTAG = "ThreadUtils";
 
+    // Time in ms until the Gecko thread is reset to normal priority.
+    private static final long PRIORITY_RESET_TIMEOUT = 10000;
+
     /**
      * Controls the action taken when a method like
      * {@link ThreadUtils#assertOnUiThread(AssertBehavior)} detects a problem.
      */
     public static enum AssertBehavior {
         NONE,
         THROW,
     }
@@ -204,30 +207,28 @@ public final class ThreadUtils {
     }
 
     /**
      * Reduces the priority of the Gecko thread, allowing other operations
      * (such as those related to the UI and database) to take precedence.
      *
      * Note that there are no guards in place to prevent multiple calls
      * to this method from conflicting with each other.
-     *
-     * @param timeout Timeout in ms after which the priority will be reset
      */
-    public static void reduceGeckoPriority(long timeout) {
+    public static void reduceGeckoPriority() {
         if (Runtime.getRuntime().availableProcessors() > 1) {
             // Don't reduce priority for multicore devices. We use availableProcessors()
             // for its fast performance. It may give false negatives (i.e. multicore
             // detected as single-core), but we can tolerate this behavior.
             return;
         }
         if (!sIsGeckoPriorityReduced && sGeckoThread != null) {
             sIsGeckoPriorityReduced = true;
             sGeckoThread.setPriority(Thread.MIN_PRIORITY);
-            getUiHandler().postDelayed(sPriorityResetRunnable, timeout);
+            getUiHandler().postDelayed(sPriorityResetRunnable, PRIORITY_RESET_TIMEOUT);
         }
     }
 
     /**
      * Resets the priority of a thread whose priority has been reduced
      * by reduceGeckoPriority.
      */
     public static void resetGeckoPriority() {