Closed Bug 1701368 Opened 3 years ago Closed 3 years ago

Tab unloading should precede other memory pressure observers

Categories

(Firefox :: Tabbed Browser, enhancement, P1)

enhancement

Tracking

()

RESOLVED FIXED
91 Branch
Fission Milestone MVP
Tracking Status
firefox91 --- fixed

People

(Reporter: haik, Assigned: toshi)

References

Details

Attachments

(7 files, 1 obsolete file)

Tab unloading (not enabled at this time) is implemented as a memory-pressure observer. Given that tab unloading may reduce memory use, we should experiment with unloading tabs first and then notifying memory-pressure observers if we are still in a low memory state.

Note that the first time we detect a low-memory situation we send a memory-pressure event with a low-memory payload. If the low memory situation persists further events have the low-memory-ongoing payload instead.

Currently all listeners tend to respond to the latter but we might switch this around: we make tab unloader respond to low-memory and everything else to low-memory-ongoing. This however does not guarantee that the low-memory-ongoing listeners will ever run.

An alternative would be to augment our nsIObserver implementation so that it's possible to prepend listeners (we currently only support appending them). Since listeners are called in the order they appear in the list prepending the tab unloader to all other listeners would guarantee it is always called first. Arguable this second solution would be simpler but maybe slightly more brittle.

Tracking for Fission M8 milestone because Toshi says this bug is a blocker for enabling tab unloading in bug 1587762 (which we are also tracking for Fission M8).

Fission Milestone: --- → M8
Assignee: nobody → tkikuchi
Severity: -- → S4
Priority: -- → P1
Blocks: 1715858

This patch splits nsAvailableMemoryWatcher into 1) an nsISupports-derived class
nsAvailableMemoryWatcherBase and 2) a platform-specific class nsAvailableMemoryWatcher,
taking out the 2) part as a new file AvailableMemoryWatcherWin.cpp without any change.

Test cases for nsAvailableMemoryWatcher will be added by a subsequent patch.

  1. Use nsAutoHandle instead of a raw HANDLE
  2. Add a dtor with MOZ_ASSERT
  3. Prevent double init
  4. Cache nsAvailableMemoryWatcher::mObserverSvc

Depends on D117669

This enables JS code to post a memory-pressure event.

Depends on D117670

With this patch, the first OnLowMemory is triggered by the memory resource
notification which is based on the available physical memory, but subsequent
OnLowMemory or OnHighMemory is triggered by the timer based on the
available commit space.

The key part of this change is the if block in nsAvailableMemoryWatcher::Notify,
where we use a single condition IsCommitSpaceLow() to declare either Low or High.
With this, OnLowMemory is called not only in the main thread but also in a worker
thread, StartPollingIfUserInteracting also needs a lock to protect mPolling.
We don't need QueryMemoryResourceNotification anymore.

Depends on D117671

This is the main part to address bug 1701368.

Before this patch, nsAvailableMemoryWatcher directly broadcasted
a memory-pressure event when we enter into a low-memory situation and
TabUnloader unloaded a tab in response to the memory-pressure message.

This patch introduces a new message "memory-watcher-notification" for
nsAvailableMemoryWatcher to send to TabUnloader without involving
other memory-pressure listeners.

With this, nsAvailableMemoryWatcher sends "memory-watcher-notification"
with a subtopic "OnLowMemory" or "OnHighMemory" accordingly. TabUnloader
is responsible for an actual action: unload a tab or send a memory-pressure.

To achieve that, this patch implements a state machine in TabUnloader,
consisting of three states: Normal, LowMemory, and MemoryPressured.
State transition happens in response to "memory-watcher-notification" from
nsAvailableMemoryWatcher. Currently we define seven transitions:

  1. Normal --(OnLowMemory)--> LowMemory
  2. Normal --(OnLowMemory)--> MemoryPressured
  3. LowMemory --(OnLowMemory)--> LowMemory
  4. LowMemory --(OnLowMemory)--> MemoryPressured
  5. LowMemory --(OnHighMemory)--> Normal
  6. MemoryPressured --(OnLowMemory)--> MemoryPressured
  7. MemoryPressured --(OnHighMemory)--> Normal

Depends on D117672

Tab unloading is a nice-to-have for our Fission Release experiment, but doesn't need to block it. I will move this bug from Fission Milestone M8 to MVP.

Fission Milestone: M8 → MVP

This patch introduces an XPCOM object which is represented by the single instance of
nsAvailableMemoryWatcherBase so that nsAvailableMemoryWatcher can synchronously
access TabUnloader.

We currently implement a watcher class for Windows only. For other platforms, what
we need to do is to define a class inherinting nsAvailableMemoryWatcherBase and
a simple factory method CreateAvailableMemoryWatcher() returning an instance of
that class.

Depends on D117672

Attachment #9226868 - Attachment description: Bug 1701368 - Part5: Introduce a state machine in TabUnloader. r=gsvelto → Bug 1701368 - Part6: Introduce a state machine in TabUnloader. r=gsvelto
Attachment #9226870 - Attachment description: Bug 1701368 - Part6: Add GTest to test nsAvailableMemoryWatcher. r=gsvelto → Bug 1701368 - Part7: Add GTest to test nsAvailableMemoryWatcher. r=gsvelto

We had NS_DispatchMemoryPressure and NS_DispatchEventualMemoryPressure
to dispatch a memory-pressure event which took MemPressure_New and
MemPressure_Ongoing to translate into "low-memory" and "low-memory-ongoing"
message respectively.

With that model, we could end up sending a wrong message if somebody
called the API with MemPressure_Ongoing without sending MemPressure_New.
To avoid that, this patch removes MemPressure_Ongoing and makes
the API decide whether it should dispatch a "new" event or "ongoing" event.

Depends on D117670

Attachment #9226868 - Attachment description: Bug 1701368 - Part6: Introduce a state machine in TabUnloader. r=gsvelto → Bug 1701368 - Part6: Tab unloading precedes memory pressure events. r=gsvelto
Attachment #9226865 - Attachment is obsolete: true
Pushed by tkikuchi@mozilla.com:
https://hg.mozilla.org/integration/autoland/rev/feca7daa9c96
Part1: Extract nsAvailableMemoryWatcher as AvailableMemoryWatcherWin.cpp. r=gsvelto
https://hg.mozilla.org/integration/autoland/rev/d773413513cf
Part2: Clean up nsAvailableMemoryWatcher.  r=gsvelto
https://hg.mozilla.org/integration/autoland/rev/98046adfc310
Part3: Remove the MemPressure_Ongoing request.  r=gsvelto
https://hg.mozilla.org/integration/autoland/rev/f3a475931a13
Part4: Make the nsAvailableMemoryWatcher timer commit-space driven.  r=gsvelto
https://hg.mozilla.org/integration/autoland/rev/38fb1e114a53
Part5: Convert nsAvailableMemoryWatcher to an XPCOM object.  r=gsvelto
https://hg.mozilla.org/integration/autoland/rev/907317341862
Part6: Tab unloading precedes memory pressure events.  r=gsvelto
https://hg.mozilla.org/integration/autoland/rev/3be9f410b666
Part7: Add GTest to test nsAvailableMemoryWatcher.  r=gsvelto

Updated the part3 to fix the compile warning in TestMemoryPressure.cpp and updated the part6 to fix the error in browser_TabUnloader.js during test-windows10-64-qr/debug-test-verify-fis-e10s TV-fis.

Flags: needinfo?(tkikuchi)
Pushed by tkikuchi@mozilla.com:
https://hg.mozilla.org/integration/autoland/rev/1251a4fedbd0
Part1: Extract nsAvailableMemoryWatcher as AvailableMemoryWatcherWin.cpp. r=gsvelto
https://hg.mozilla.org/integration/autoland/rev/857bb33999bd
Part2: Clean up nsAvailableMemoryWatcher.  r=gsvelto
https://hg.mozilla.org/integration/autoland/rev/278e8d0bd4dc
Part3: Remove the MemPressure_Ongoing request.  r=gsvelto
https://hg.mozilla.org/integration/autoland/rev/a2c139554e9e
Part4: Make the nsAvailableMemoryWatcher timer commit-space driven.  r=gsvelto
https://hg.mozilla.org/integration/autoland/rev/9c9913e934af
Part5: Convert nsAvailableMemoryWatcher to an XPCOM object.  r=gsvelto
https://hg.mozilla.org/integration/autoland/rev/b88c3bce751e
Part6: Tab unloading precedes memory pressure events.  r=gsvelto
https://hg.mozilla.org/integration/autoland/rev/f987c607501f
Part7: Add GTest to test nsAvailableMemoryWatcher.  r=gsvelto
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: