Bug 1767346 - Use browsing context activeness rather than renderLayers to determine process priority. r=mccr8,mconley,geckoview-reviewers,agi

For desktop this should basically have no impact (maybe impacts tab
warming, but if we wanted we could set the priority hint from the tab
switcher the same way we set renderLayers), but Fenix always has
renderLayers as true, effectively, so we were never de-prioritizing the
background tab processes.

Differential Revision: https://phabricator.services.mozilla.com/D145351
This commit is contained in:
Emilio Cobos Álvarez 2022-05-20 00:48:32 +00:00
parent a051b1b2bc
commit d6edcc48bb
8 changed files with 85 additions and 70 deletions

View File

@ -21,6 +21,7 @@
#endif
#include "mozilla/AppShutdown.h"
#include "mozilla/dom/CanonicalBrowsingContext.h"
#include "mozilla/dom/BrowserHost.h"
#include "mozilla/dom/BrowserChild.h"
#include "mozilla/dom/BrowserParent.h"
#include "mozilla/dom/BrowsingContextGroup.h"
@ -2641,25 +2642,29 @@ void BrowsingContext::DidSet(FieldIndex<IDX_ExplicitActive>,
if (IsTop()) {
Group()->UpdateToplevelsSuspendedIfNeeded();
if (XRE_IsParentProcess()) {
auto* bc = Canonical();
if (BrowserParent* bp = bc->GetBrowserParent()) {
bp->RecomputeProcessPriority();
#if defined(XP_WIN) && defined(ACCESSIBILITY)
if (XRE_IsParentProcess() && a11y::Compatibility::IsDolphin()) {
// update active accessible documents on windows
if (BrowserParent* bp = Canonical()->GetBrowserParent()) {
if (a11y::DocAccessibleParent* tabDoc =
bp->GetTopLevelDocAccessible()) {
HWND window = tabDoc->GetEmulatedWindowHandle();
MOZ_ASSERT(window);
if (window) {
if (isActive) {
a11y::nsWinUtils::ShowNativeWindow(window);
} else {
a11y::nsWinUtils::HideNativeWindow(window);
if (a11y::Compatibility::IsDolphin()) {
// update active accessible documents on windows
if (a11y::DocAccessibleParent* tabDoc =
bp->GetTopLevelDocAccessible()) {
HWND window = tabDoc->GetEmulatedWindowHandle();
MOZ_ASSERT(window);
if (window) {
if (isActive) {
a11y::nsWinUtils::ShowNativeWindow(window);
} else {
a11y::nsWinUtils::HideNativeWindow(window);
}
}
}
}
#endif
}
}
#endif
}
PreOrderWalk([&](BrowsingContext* aContext) {

View File

@ -120,10 +120,6 @@ BrowserHost::SetRenderLayers(bool aRenderLayers) {
return NS_OK;
}
bool priorityHint;
GetPriorityHint(&priorityHint);
ProcessPriorityManager::BrowserPriorityChanged(
GetBrowsingContext()->Canonical(), priorityHint || aRenderLayers);
mRoot->SetRenderLayers(aRenderLayers);
return NS_OK;
}
@ -131,11 +127,7 @@ BrowserHost::SetRenderLayers(bool aRenderLayers) {
/* readonly attribute boolean hasLayers; */
NS_IMETHODIMP
BrowserHost::GetHasLayers(bool* aHasLayers) {
if (!mRoot) {
*aHasLayers = false;
return NS_OK;
}
*aHasLayers = mRoot->GetHasLayers();
*aHasLayers = mRoot && mRoot->GetHasLayers();
return NS_OK;
}
@ -145,27 +137,19 @@ BrowserHost::SetPriorityHint(bool aPriorityHint) {
if (!mRoot) {
return NS_OK;
}
bool renderLayers;
GetRenderLayers(&renderLayers);
ProcessPriorityManager::BrowserPriorityChanged(
GetBrowsingContext()->Canonical(), aPriorityHint || renderLayers);
mRoot->SetPriorityHint(aPriorityHint);
return NS_OK;
}
NS_IMETHODIMP
BrowserHost::GetPriorityHint(bool* aPriorityHint) {
if (!mRoot) {
*aPriorityHint = false;
return NS_OK;
}
*aPriorityHint = mRoot->GetPriorityHint();
*aPriorityHint = mRoot && mRoot->GetPriorityHint();
return NS_OK;
}
/* void resolutionChanged (); */
NS_IMETHODIMP
BrowserHost::NotifyResolutionChanged(void) {
BrowserHost::NotifyResolutionChanged() {
if (!mRoot) {
return NS_OK;
}
@ -177,13 +161,13 @@ BrowserHost::NotifyResolutionChanged(void) {
/* void deprioritize (); */
NS_IMETHODIMP
BrowserHost::Deprioritize(void) {
BrowserHost::Deprioritize() {
if (!mRoot) {
return NS_OK;
}
ProcessPriorityManager::BrowserPriorityChanged(
GetBrowsingContext()->Canonical(),
/* aPriority = */ false);
auto* bc = GetBrowsingContext()->Canonical();
ProcessPriorityManager::BrowserPriorityChanged(bc,
/* aPriority = */ false);
return NS_OK;
}

View File

@ -162,7 +162,6 @@ using namespace mozilla::widget;
using namespace mozilla::gfx;
using mozilla::LazyLogModule;
using mozilla::Unused;
extern mozilla::LazyLogModule gSHIPBFCacheLog;
@ -243,10 +242,18 @@ BrowserParent::BrowserParent(ContentParent* aManager, const TabId& aTabId,
// that some input events are dispatched before PBrowserConstructor.
mIsReadyToHandleInputEvents = !ContentParent::IsInputEventQueueSupported();
// Make sure to compute our process priority if needed before the block of
// code below. This makes sure the block below prioritizes our process if
// needed.
if (aBrowsingContext->IsTop()) {
RecomputeProcessPriority();
}
// If we're in a BC tree that is active with respect to the priority manager,
// ensure that this new BrowserParent is marked as active. This ensures that
// the process will be prioritized in a cross-site iframe navigation in an
// active tab.
// active tab, and also that the process is correctly prioritized if we got
// created for a browsing context which was already active.
if (aBrowsingContext->Top()->IsPriorityActive()) {
ProcessPriorityManager::BrowserPriorityChanged(this, true);
}
@ -3477,6 +3484,13 @@ bool BrowserParent::GetPriorityHint() { return mPriorityHint; }
void BrowserParent::SetPriorityHint(bool aPriorityHint) {
mPriorityHint = aPriorityHint;
RecomputeProcessPriority();
}
void BrowserParent::RecomputeProcessPriority() {
auto* bc = GetBrowsingContext();
ProcessPriorityManager::BrowserPriorityChanged(
bc, bc->IsActive() || mPriorityHint);
}
void BrowserParent::PreserveLayers(bool aPreserveLayers) {

View File

@ -132,6 +132,8 @@ class BrowserParent final : public PBrowserParent,
CanonicalBrowsingContext* GetBrowsingContext() { return mBrowsingContext; }
void RecomputeProcessPriority();
already_AddRefed<nsILoadContext> GetLoadContext();
Element* GetOwnerElement() const { return mFrameElement; }

View File

@ -509,10 +509,20 @@ void ProcessPriorityManagerImpl::NotifyProcessPriorityChanged(
}
}
static nsCString BCToString(dom::CanonicalBrowsingContext* aBC) {
nsCOMPtr<nsIURI> uri = aBC->GetCurrentURI();
return nsPrintfCString("id=%" PRIu64 " uri=%s active=%d pactive=%d",
aBC->Id(),
uri ? uri->GetSpecOrDefault().get() : nullptr,
aBC->IsActive(), aBC->IsPriorityActive());
}
void ProcessPriorityManagerImpl::BrowserPriorityChanged(
dom::CanonicalBrowsingContext* aBC, bool aPriority) {
MOZ_ASSERT(aBC->IsTop());
LOG("BrowserPriorityChanged(%s, %d)\n", BCToString(aBC).get(), aPriority);
bool alreadyActive = aBC->IsPriorityActive();
if (alreadyActive == aPriority) {
return;
@ -525,6 +535,8 @@ void ProcessPriorityManagerImpl::BrowserPriorityChanged(
aBC->PreOrderWalk([&](BrowsingContext* aContext) {
CanonicalBrowsingContext* canonical = aContext->Canonical();
LOG("PreOrderWalk for %p: %p -> %p, %p\n", aBC, canonical,
canonical->GetContentParent(), canonical->GetBrowserParent());
if (ContentParent* cp = canonical->GetContentParent()) {
if (RefPtr pppm = GetParticularProcessPriorityManager(cp)) {
if (auto* bp = canonical->GetBrowserParent()) {
@ -537,6 +549,8 @@ void ProcessPriorityManagerImpl::BrowserPriorityChanged(
void ProcessPriorityManagerImpl::BrowserPriorityChanged(
BrowserParent* aBrowserParent, bool aPriority) {
LOG("BrowserPriorityChanged(bp=%p, %d)\n", aBrowserParent, aPriority);
if (RefPtr pppm =
GetParticularProcessPriorityManager(aBrowserParent->Manager())) {
Telemetry::ScalarAdd(
@ -766,13 +780,14 @@ void ParticularProcessPriorityManager::SetPriorityNow(
return;
}
LOGP("Changing priority from %s to %s (cp=%p).",
ProcessPriorityToString(mPriority), ProcessPriorityToString(aPriority),
mContentParent);
if (!mContentParent || mPriority == aPriority) {
return;
}
LOGP("Changing priority from %s to %s.", ProcessPriorityToString(mPriority),
ProcessPriorityToString(aPriority));
PROFILER_MARKER(
"Subprocess Priority", OTHER,
MarkerOptions(MarkerThreadId::MainThread(), MarkerStack::Capture()),

View File

@ -318,6 +318,19 @@ add_task(async function test_normal_background_tab() {
"PriorityHint of the original tab should be false on default"
);
// Changing renderLayers doesn't change priority of the background tab.
originalTab.linkedBrowser.preserveLayers(true);
originalTab.linkedBrowser.renderLayers = true;
await new Promise(resolve =>
// eslint-disable-next-line mozilla/no-arbitrary-setTimeout
setTimeout(resolve, WAIT_FOR_CHANGE_TIME_MS)
);
Assert.equal(
gTabPriorityWatcher.currentPriority(origtabID),
PROCESS_PRIORITY_BACKGROUND,
"Tab didn't get prioritized only due to renderLayers"
);
// Test when priorityHint is true, the original tab priority
// becomes PROCESS_PRIORITY_FOREGROUND.
originalTab.linkedBrowser.frameLoader.remoteTab.priorityHint = true;
@ -364,6 +377,9 @@ add_task(async function test_normal_background_tab() {
PROCESS_PRIORITY_FOREGROUND,
"Setting priorityHint to false should maintain the new tab priority as foreground"
);
originalTab.linkedBrowser.preserveLayers(false);
originalTab.linkedBrowser.renderLayers = false;
}
);
});

View File

@ -10,6 +10,8 @@
#include "mozilla/java/GeckoProcessTypeWrappers.h"
#include "mozilla/java/ServiceAllocatorWrappers.h"
using namespace mozilla::hal;
/**
* Bucket the Gecko HAL process priority level into one of the three Android
* priority levels.

View File

@ -95,12 +95,15 @@ class GeckoViewTest : BaseSessionTest() {
val lowPids = low.map { sessionRule.getSessionPid(it) }.toSet()
UiThreadUtils.waitForCondition({
getContentProcessesPriority(highPids).count { it > 100 } == 0
&& getContentProcessesPriority(lowPids).count { it < 300 } == 0
val shouldBeHighPri = getContentProcessesOomScore(highPids)
val shouldBeLowPri = getContentProcessesOomScore(lowPids)
// Note that higher oom score means less priority
shouldBeHighPri.count { it > 100 } == 0
&& shouldBeLowPri.count { it < 300 } == 0
}, env.defaultTimeoutMillis)
}
fun getContentProcessesPriority(pids: Collection<Int>) : List<Int> {
fun getContentProcessesOomScore(pids: Collection<Int>) : List<Int> {
return pids.map { pid ->
File("/proc/$pid/oom_score").readText(Charsets.UTF_8).trim().toInt()
}
@ -162,29 +165,6 @@ class GeckoViewTest : BaseSessionTest() {
}
}
@Test
@NullDelegate(Autofill.Delegate::class)
fun extensionCurrentTabRaisesPriority() {
// Bug 1767346
assumeThat(false, equalTo(true))
val otherSession = setupPriorityTest()
// Setting priorityHint to PRIORITY_HIGH raises priority
mainSession.setPriorityHint(GeckoSession.PRIORITY_HIGH)
waitUntilContentProcessPriority(
high = listOf(mainSession, otherSession), low = listOf()
)
// Setting the priorityHint to default should lower priority
mainSession.setPriorityHint(GeckoSession.PRIORITY_DEFAULT)
waitUntilContentProcessPriority(
high = listOf(mainSession), low = listOf(otherSession)
)
}
@Test
@NullDelegate(Autofill.Delegate::class)
fun processPriorityTest() {
@ -221,9 +201,6 @@ class GeckoViewTest : BaseSessionTest() {
@Test
@NullDelegate(Autofill.Delegate::class)
fun setPriorityHint() {
// Bug 1767346
assumeThat(false, equalTo(true))
val otherSession = setupPriorityTest()
// Setting priorityHint to PRIORITY_HIGH raises priority