Commit 66b31a7e authored by Nika Layzell's avatar Nika Layzell
Browse files

Bug 1728331 - Part 1: Avoid cycling between processes when navigating within a tab, r=smaug

This patch replaces the previous process selection infrastructure with a
new setup implemented entirely in C++, which should more accurately
track the set of processes in use, and should encourage re-use of the
existing content process when navigating by not counting the current
tab.

This approach intentionally allows for process switching to another
process during navigation if there is uneven load between processes to
encourage balanced process use.

I think this may also fix some of the session restore issues with many
tabs using the same process, rather than being spread over 4, as we now
track a tab earlier in its lifecycle before the BrowserParent instance
is created.

Differential Revision: https://phabricator.services.mozilla.com/D126405
parent 15fd5a00
Loading
Loading
Loading
Loading
+5 −4
Original line number Diff line number Diff line
@@ -1758,7 +1758,7 @@ void CanonicalBrowsingContext::PendingRemotenessChange::Clear() {
  // When this PendingRemotenessChange was created, it was given a
  // `mContentParent`.
  if (mContentParent) {
    mContentParent->RemoveKeepAlive();
    mContentParent->RemoveKeepAlive(mTarget->BrowserId());
    mContentParent = nullptr;
  }

@@ -1914,7 +1914,7 @@ CanonicalBrowsingContext::ChangeRemoteness(
    // Switching to local, so we don't need to create a new process, and will
    // instead use our embedder process.
    change->mContentParent = embedderBrowser->Manager();
    change->mContentParent->AddKeepAlive();
    change->mContentParent->AddKeepAlive(BrowserId());
    change->ProcessLaunched();
    return promise.forget();
  }
@@ -1933,7 +1933,7 @@ CanonicalBrowsingContext::ChangeRemoteness(
      aOptions.mReplaceBrowsingContext &&
      aOptions.mRemoteType == existingProcess->GetRemoteType()) {
    change->mContentParent = existingProcess;
    change->mContentParent->AddKeepAlive();
    change->mContentParent->AddKeepAlive(BrowserId());
    change->ProcessLaunched();
    return promise.forget();
  }
@@ -1955,6 +1955,7 @@ CanonicalBrowsingContext::ChangeRemoteness(
  change->mContentParent = ContentParent::GetNewOrUsedLaunchingBrowserProcess(
      /* aRemoteType = */ aOptions.mRemoteType,
      /* aGroup = */ finalGroup,
      /* aBrowserId */ BrowserId(),
      /* aPriority = */ hal::PROCESS_PRIORITY_FOREGROUND,
      /* aPreferUsed = */ preferUsed);
  if (!change->mContentParent) {
@@ -1965,7 +1966,7 @@ CanonicalBrowsingContext::ChangeRemoteness(
  // Add a KeepAlive used by this ContentParent, which will be cleared when
  // the change is complete. This should prevent the process dying before
  // we're ready to use it.
  change->mContentParent->AddKeepAlive();
  change->mContentParent->AddKeepAlive(BrowserId());
  if (change->mContentParent->IsLaunching()) {
    change->mContentParent->WaitForLaunchAsync()->Then(
        GetMainThreadSerialEventTarget(), __func__,

dom/base/ProcessSelector.jsm

deleted100644 → 0
+0 −60
Original line number Diff line number Diff line
/* 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/. */

// Fills up aProcesses until max and then selects randomly from the available
// ones.
function RandomSelector() {}

RandomSelector.prototype = {
  classID: Components.ID("{c616fcfd-9737-41f1-aa74-cee72a38f91b}"),
  QueryInterface: ChromeUtils.generateQI(["nsIContentProcessProvider"]),

  provideProcess(aType, aProcesses, aMaxCount) {
    if (aProcesses.length < aMaxCount) {
      return Ci.nsIContentProcessProvider.NEW_PROCESS;
    }

    return Math.floor(Math.random() * aMaxCount);
  },
};

// Fills up aProcesses until max and then selects one from the available
// ones that host the least number of tabs.
function MinTabSelector() {}

MinTabSelector.prototype = {
  classID: Components.ID("{2dc08eaf-6eef-4394-b1df-a3a927c1290b}"),
  QueryInterface: ChromeUtils.generateQI(["nsIContentProcessProvider"]),

  provideProcess(aType, aProcesses, aMaxCount) {
    let min = Number.MAX_VALUE;
    let candidate = Ci.nsIContentProcessProvider.NEW_PROCESS;

    // The reason for not directly using aProcesses.length here is because if
    // we keep processes alive for testing but want a test to use only single
    // content process we can just keep relying on dom.ipc.processCount = 1
    // this way.
    let numIters = Math.min(aProcesses.length, aMaxCount);

    for (let i = 0; i < numIters; i++) {
      let process = aProcesses[i];
      let tabCount = process.tabCount;
      if (tabCount < min) {
        min = tabCount;
        candidate = i;
      }
    }

    // If all current processes have at least one tab and we have not yet
    // reached the maximum, spawn a new process.
    if (min > 0 && aProcesses.length < aMaxCount) {
      return Ci.nsIContentProcessProvider.NEW_PROCESS;
    }

    // Otherwise we use candidate.
    return candidate;
  },
};

var EXPORTED_SYMBOLS = ["RandomSelector", "MinTabSelector"];
+0 −11
Original line number Diff line number Diff line
@@ -13,17 +13,6 @@ Classes = [
        'jsm': 'resource://gre/modules/ContentAreaDropListener.jsm',
        'constructor': 'ContentAreaDropListener',
    },
    {
        'cid': '{c616fcfd-9737-41f1-aa74-cee72a38f91b}',
        'jsm': 'resource://gre/modules/ProcessSelector.jsm',
        'constructor': 'RandomSelector',
    },
    {
        'cid': '{2dc08eaf-6eef-4394-b1df-a3a927c1290b}',
        'contract_ids': ['@mozilla.org/ipc/processselector;1'],
        'jsm': 'resource://gre/modules/ProcessSelector.jsm',
        'constructor': 'MinTabSelector',
    },
    {
        'cid': '{e740ddb4-18b4-4aac-8ae1-9b0f4320769d}',
        'contract_ids': ['@mozilla.org/dom/slow-script-debug;1'],
+0 −1
Original line number Diff line number Diff line
@@ -521,7 +521,6 @@ EXTRA_JS_MODULES += [
    "DOMRequestHelper.jsm",
    "IndexedDBHelper.jsm",
    "LocationHelper.jsm",
    "ProcessSelector.jsm",
    "SlowScriptDebug.jsm",
]

+0 −1
Original line number Diff line number Diff line
@@ -15,7 +15,6 @@ XPIDL_SOURCES += [
    "nsIBrowserUsage.idl",
    "nsIContentPermissionPrompt.idl",
    "nsIContentPrefService2.idl",
    "nsIContentProcess.idl",
    "nsIDOMChromeWindow.idl",
    "nsIDOMGlobalPropertyInitializer.idl",
    "nsIDOMWindow.idl",
Loading