|
|
|
@ -9,9 +9,9 @@
|
|
|
|
|
#if defined(XP_WIN)
|
|
|
|
|
# include "mozilla/WindowsVersion.h"
|
|
|
|
|
# include "nsExceptionHandler.h"
|
|
|
|
|
# include "nsICrashReporter.h"
|
|
|
|
|
# include "nsIMemoryReporter.h"
|
|
|
|
|
# include "nsMemoryPressure.h"
|
|
|
|
|
# include "memoryapi.h"
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#include "nsIObserver.h"
|
|
|
|
@ -22,7 +22,6 @@
|
|
|
|
|
#include "nsThreadUtils.h"
|
|
|
|
|
#include "nsXULAppAPI.h"
|
|
|
|
|
|
|
|
|
|
#include "mozilla/Mutex.h"
|
|
|
|
|
#include "mozilla/ResultExtensions.h"
|
|
|
|
|
#include "mozilla/Services.h"
|
|
|
|
|
#include "mozilla/Unused.h"
|
|
|
|
@ -52,19 +51,13 @@ typedef struct _HEAP_OPTIMIZE_RESOURCES_INFORMATION {
|
|
|
|
|
} HEAP_OPTIMIZE_RESOURCES_INFORMATION, *PHEAP_OPTIMIZE_RESOURCES_INFORMATION;
|
|
|
|
|
# endif
|
|
|
|
|
|
|
|
|
|
Atomic<uint32_t, MemoryOrdering::Relaxed> sNumLowPhysicalMemEvents;
|
|
|
|
|
Atomic<uint32_t, MemoryOrdering::Relaxed> sNumLowVirtualMemEvents;
|
|
|
|
|
Atomic<uint32_t, MemoryOrdering::Relaxed> sNumLowCommitSpaceEvents;
|
|
|
|
|
|
|
|
|
|
// This class is used to monitor low memory events delivered by Windows via
|
|
|
|
|
// memory resource notification objects. When we enter a low memory scenario
|
|
|
|
|
// the LowMemoryCallback() is invoked by Windows. This initial call triggers
|
|
|
|
|
// an nsITimer that polls to see when the low memory condition has been lifted.
|
|
|
|
|
// When it has, we'll stop polling and start waiting for the next
|
|
|
|
|
// LowMemoryCallback(). Meanwhile, the polling may be stopped and restarted by
|
|
|
|
|
// user-interaction events from the observer service.
|
|
|
|
|
class nsAvailableMemoryWatcher final : public nsIObserver,
|
|
|
|
|
public nsITimerCallback {
|
|
|
|
|
public:
|
|
|
|
|
NS_DECL_THREADSAFE_ISUPPORTS
|
|
|
|
|
NS_DECL_ISUPPORTS
|
|
|
|
|
NS_DECL_NSIOBSERVER
|
|
|
|
|
NS_DECL_NSITIMERCALLBACK
|
|
|
|
|
|
|
|
|
@ -72,40 +65,41 @@ class nsAvailableMemoryWatcher final : public nsIObserver,
|
|
|
|
|
nsresult Init();
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
// Fire a low-memory notification if we have less than this many bytes of
|
|
|
|
|
// virtual address space available.
|
|
|
|
|
# if defined(HAVE_64BIT_BUILD)
|
|
|
|
|
static const size_t kLowVirtualMemoryThreshold = 0;
|
|
|
|
|
# else
|
|
|
|
|
static const size_t kLowVirtualMemoryThreshold = 384 * 1024 * 1024;
|
|
|
|
|
# endif
|
|
|
|
|
|
|
|
|
|
// Fire a low-memory notification if we have less than this many bytes of
|
|
|
|
|
// commit space (physical memory plus page file) left.
|
|
|
|
|
static const size_t kLowCommitSpaceThreshold = 384 * 1024 * 1024;
|
|
|
|
|
|
|
|
|
|
// Don't fire a low-memory notification more often than this interval.
|
|
|
|
|
static const uint32_t kLowMemoryNotificationIntervalMS = 10000;
|
|
|
|
|
|
|
|
|
|
// Poll the amount of free memory at this rate.
|
|
|
|
|
static const uint32_t kPollingIntervalMS = 1000;
|
|
|
|
|
|
|
|
|
|
// Observer topics we subscribe to, see below.
|
|
|
|
|
static const char* const kObserverTopics[];
|
|
|
|
|
|
|
|
|
|
static VOID CALLBACK LowMemoryCallback(PVOID aContext, BOOLEAN aIsTimer);
|
|
|
|
|
static void RecordLowMemoryEvent();
|
|
|
|
|
static bool IsVirtualMemoryLow(const MEMORYSTATUSEX& aStat);
|
|
|
|
|
static bool IsCommitSpaceLow(const MEMORYSTATUSEX& aStat);
|
|
|
|
|
|
|
|
|
|
~nsAvailableMemoryWatcher(){};
|
|
|
|
|
bool RegisterMemoryResourceHandler();
|
|
|
|
|
void UnregisterMemoryResourceHandler();
|
|
|
|
|
void Shutdown(const MutexAutoLock&);
|
|
|
|
|
bool ListenForLowMemory();
|
|
|
|
|
void OnLowMemory(const MutexAutoLock&);
|
|
|
|
|
void OnHighMemory(const MutexAutoLock&);
|
|
|
|
|
bool IsMemoryLow() const;
|
|
|
|
|
void StartPollingIfUserInteracting();
|
|
|
|
|
void StopPolling();
|
|
|
|
|
void StopPollingIfUserIdle(const MutexAutoLock&);
|
|
|
|
|
void OnUserInteracting(const MutexAutoLock&);
|
|
|
|
|
void OnUserIdle(const MutexAutoLock&);
|
|
|
|
|
bool OngoingMemoryPressure() { return mUnderMemoryPressure; }
|
|
|
|
|
void AdjustPollingInterval(const bool aLowMemory);
|
|
|
|
|
void SendMemoryPressureEvent();
|
|
|
|
|
void MaybeSendMemoryPressureStopEvent();
|
|
|
|
|
void MaybeSaveMemoryReport();
|
|
|
|
|
void Shutdown();
|
|
|
|
|
|
|
|
|
|
// The publicly available methods (::Observe() and ::Notify()) are called on
|
|
|
|
|
// the main thread while the ::LowMemoryCallback() method is called by an
|
|
|
|
|
// external thread. All functions called from those must acquire a lock on
|
|
|
|
|
// this mutex before accessing the object's fields to prevent races.
|
|
|
|
|
Mutex mMutex;
|
|
|
|
|
nsCOMPtr<nsITimer> mTimer;
|
|
|
|
|
HANDLE mLowMemoryHandle;
|
|
|
|
|
HANDLE mWaitHandle;
|
|
|
|
|
bool mPolling;
|
|
|
|
|
bool mInteracting;
|
|
|
|
|
bool mUnderMemoryPressure;
|
|
|
|
|
bool mSavedReport;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const char* const nsAvailableMemoryWatcher::kObserverTopics[] = {
|
|
|
|
@ -117,13 +111,7 @@ const char* const nsAvailableMemoryWatcher::kObserverTopics[] = {
|
|
|
|
|
NS_IMPL_ISUPPORTS(nsAvailableMemoryWatcher, nsIObserver, nsITimerCallback)
|
|
|
|
|
|
|
|
|
|
nsAvailableMemoryWatcher::nsAvailableMemoryWatcher()
|
|
|
|
|
: mMutex("low memory callback mutex"),
|
|
|
|
|
mTimer(nullptr),
|
|
|
|
|
mLowMemoryHandle(nullptr),
|
|
|
|
|
mWaitHandle(nullptr),
|
|
|
|
|
mPolling(false),
|
|
|
|
|
mInteracting(false),
|
|
|
|
|
mUnderMemoryPressure(false) {}
|
|
|
|
|
: mTimer(nullptr), mUnderMemoryPressure(false), mSavedReport(false) {}
|
|
|
|
|
|
|
|
|
|
nsresult nsAvailableMemoryWatcher::Init() {
|
|
|
|
|
mTimer = NS_NewTimer();
|
|
|
|
@ -131,62 +119,18 @@ nsresult nsAvailableMemoryWatcher::Init() {
|
|
|
|
|
nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
|
|
|
|
|
MOZ_ASSERT(observerService);
|
|
|
|
|
|
|
|
|
|
if (!RegisterMemoryResourceHandler()) {
|
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (auto topic : kObserverTopics) {
|
|
|
|
|
nsresult rv = observerService->AddObserver(this, topic,
|
|
|
|
|
/* ownsWeak */ false);
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MOZ_TRY(mTimer->InitWithCallback(this, kPollingIntervalMS,
|
|
|
|
|
nsITimer::TYPE_REPEATING_SLACK));
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// static
|
|
|
|
|
VOID CALLBACK nsAvailableMemoryWatcher::LowMemoryCallback(PVOID aContext,
|
|
|
|
|
BOOLEAN aIsTimer) {
|
|
|
|
|
nsAvailableMemoryWatcher* watcher =
|
|
|
|
|
static_cast<nsAvailableMemoryWatcher*>(aContext);
|
|
|
|
|
if (!aIsTimer) {
|
|
|
|
|
MutexAutoLock lock(watcher->mMutex);
|
|
|
|
|
watcher->OnLowMemory(lock);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// static
|
|
|
|
|
void nsAvailableMemoryWatcher::RecordLowMemoryEvent() {
|
|
|
|
|
sNumLowPhysicalMemEvents++;
|
|
|
|
|
CrashReporter::AnnotateCrashReport(
|
|
|
|
|
CrashReporter::Annotation::LowPhysicalMemoryEvents,
|
|
|
|
|
sNumLowPhysicalMemEvents);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool nsAvailableMemoryWatcher::RegisterMemoryResourceHandler(void) {
|
|
|
|
|
mLowMemoryHandle =
|
|
|
|
|
::CreateMemoryResourceNotification(LowMemoryResourceNotification);
|
|
|
|
|
|
|
|
|
|
if (!mLowMemoryHandle) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ListenForLowMemory();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nsAvailableMemoryWatcher::UnregisterMemoryResourceHandler() {
|
|
|
|
|
if (mWaitHandle) {
|
|
|
|
|
Unused << ::UnregisterWait(mWaitHandle);
|
|
|
|
|
mWaitHandle = nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mLowMemoryHandle) {
|
|
|
|
|
Unused << ::CloseHandle(mLowMemoryHandle);
|
|
|
|
|
mLowMemoryHandle = nullptr;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nsAvailableMemoryWatcher::Shutdown(const MutexAutoLock&) {
|
|
|
|
|
void nsAvailableMemoryWatcher::Shutdown() {
|
|
|
|
|
nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
|
|
|
|
|
MOZ_ASSERT(observerService);
|
|
|
|
|
|
|
|
|
@ -198,88 +142,95 @@ void nsAvailableMemoryWatcher::Shutdown(const MutexAutoLock&) {
|
|
|
|
|
mTimer->Cancel();
|
|
|
|
|
mTimer = nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UnregisterMemoryResourceHandler();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool nsAvailableMemoryWatcher::ListenForLowMemory(void) {
|
|
|
|
|
if (mLowMemoryHandle && !mWaitHandle) {
|
|
|
|
|
return ::RegisterWaitForSingleObject(
|
|
|
|
|
&mWaitHandle, mLowMemoryHandle, LowMemoryCallback, this, INFINITE,
|
|
|
|
|
WT_EXECUTEDEFAULT | WT_EXECUTEONLYONCE);
|
|
|
|
|
/* static */
|
|
|
|
|
bool nsAvailableMemoryWatcher::IsVirtualMemoryLow(const MEMORYSTATUSEX& aStat) {
|
|
|
|
|
if ((kLowVirtualMemoryThreshold != 0) &&
|
|
|
|
|
(aStat.ullAvailVirtual < kLowVirtualMemoryThreshold)) {
|
|
|
|
|
sNumLowVirtualMemEvents++;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nsAvailableMemoryWatcher::OnLowMemory(const MutexAutoLock&) {
|
|
|
|
|
mUnderMemoryPressure = true;
|
|
|
|
|
::UnregisterWait(mWaitHandle);
|
|
|
|
|
mWaitHandle = nullptr;
|
|
|
|
|
RecordLowMemoryEvent();
|
|
|
|
|
NS_DispatchEventualMemoryPressure(MemPressure_New);
|
|
|
|
|
StartPollingIfUserInteracting();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nsAvailableMemoryWatcher::OnHighMemory(const MutexAutoLock&) {
|
|
|
|
|
mUnderMemoryPressure = false;
|
|
|
|
|
NS_DispatchEventualMemoryPressure(MemPressure_Stopping);
|
|
|
|
|
StopPolling();
|
|
|
|
|
ListenForLowMemory();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool nsAvailableMemoryWatcher::IsMemoryLow(void) const {
|
|
|
|
|
BOOL lowMemory = FALSE;
|
|
|
|
|
if (::QueryMemoryResourceNotification(mLowMemoryHandle, &lowMemory)) {
|
|
|
|
|
return lowMemory;
|
|
|
|
|
/* static */
|
|
|
|
|
bool nsAvailableMemoryWatcher::IsCommitSpaceLow(const MEMORYSTATUSEX& aStat) {
|
|
|
|
|
if ((kLowCommitSpaceThreshold != 0) &&
|
|
|
|
|
(aStat.ullAvailPageFile < kLowCommitSpaceThreshold)) {
|
|
|
|
|
sNumLowCommitSpaceEvents++;
|
|
|
|
|
CrashReporter::AnnotateCrashReport(
|
|
|
|
|
CrashReporter::Annotation::LowCommitSpaceEvents,
|
|
|
|
|
uint32_t(sNumLowCommitSpaceEvents));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nsAvailableMemoryWatcher::StartPollingIfUserInteracting(void) {
|
|
|
|
|
if (mInteracting && !mPolling) {
|
|
|
|
|
if (NS_SUCCEEDED(
|
|
|
|
|
mTimer->InitWithCallback(this, kLowMemoryNotificationIntervalMS,
|
|
|
|
|
nsITimer::TYPE_REPEATING_SLACK))) {
|
|
|
|
|
mPolling = true;
|
|
|
|
|
void nsAvailableMemoryWatcher::SendMemoryPressureEvent() {
|
|
|
|
|
MemoryPressureState state =
|
|
|
|
|
OngoingMemoryPressure() ? MemPressure_Ongoing : MemPressure_New;
|
|
|
|
|
NS_DispatchEventualMemoryPressure(state);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nsAvailableMemoryWatcher::MaybeSendMemoryPressureStopEvent() {
|
|
|
|
|
if (OngoingMemoryPressure()) {
|
|
|
|
|
NS_DispatchEventualMemoryPressure(MemPressure_Stopping);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nsAvailableMemoryWatcher::MaybeSaveMemoryReport() {
|
|
|
|
|
if (!mSavedReport && OngoingMemoryPressure()) {
|
|
|
|
|
nsCOMPtr<nsICrashReporter> cr =
|
|
|
|
|
do_GetService("@mozilla.org/toolkit/crash-reporter;1");
|
|
|
|
|
if (cr) {
|
|
|
|
|
if (NS_SUCCEEDED(cr->SaveMemoryReport())) {
|
|
|
|
|
mSavedReport = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nsAvailableMemoryWatcher::StopPolling(void) {
|
|
|
|
|
mTimer->Cancel();
|
|
|
|
|
mPolling = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nsAvailableMemoryWatcher::StopPollingIfUserIdle(const MutexAutoLock&) {
|
|
|
|
|
if (!mInteracting) {
|
|
|
|
|
StopPolling();
|
|
|
|
|
void nsAvailableMemoryWatcher::AdjustPollingInterval(const bool aLowMemory) {
|
|
|
|
|
if (aLowMemory) {
|
|
|
|
|
// We entered a low-memory state, wait for a longer interval before polling
|
|
|
|
|
// again as there's no point in rapidly sending further notifications.
|
|
|
|
|
mTimer->SetDelay(kLowMemoryNotificationIntervalMS);
|
|
|
|
|
} else if (OngoingMemoryPressure()) {
|
|
|
|
|
// We were under memory pressure but we're not anymore, resume polling at
|
|
|
|
|
// a faster pace.
|
|
|
|
|
mTimer->SetDelay(kPollingIntervalMS);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nsAvailableMemoryWatcher::OnUserInteracting(const MutexAutoLock&) {
|
|
|
|
|
mInteracting = true;
|
|
|
|
|
if (mUnderMemoryPressure) {
|
|
|
|
|
StartPollingIfUserInteracting();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nsAvailableMemoryWatcher::OnUserIdle(const MutexAutoLock&) {
|
|
|
|
|
mInteracting = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Timer callback, polls the low memory resource notification to detect when
|
|
|
|
|
// we've freed enough memory or if we have to send more memory pressure events.
|
|
|
|
|
// Polling stops automatically when the user is not interacting with the UI.
|
|
|
|
|
// Timer callback, polls memory stats to detect low-memory conditions. This
|
|
|
|
|
// will send memory-pressure events if memory is running low and adjust the
|
|
|
|
|
// polling interval accordingly.
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
nsAvailableMemoryWatcher::Notify(nsITimer* aTimer) {
|
|
|
|
|
MutexAutoLock lock(mMutex);
|
|
|
|
|
StopPollingIfUserIdle(lock);
|
|
|
|
|
MEMORYSTATUSEX stat;
|
|
|
|
|
stat.dwLength = sizeof(stat);
|
|
|
|
|
bool success = GlobalMemoryStatusEx(&stat);
|
|
|
|
|
|
|
|
|
|
if (IsMemoryLow()) {
|
|
|
|
|
NS_DispatchEventualMemoryPressure(MemPressure_Ongoing);
|
|
|
|
|
} else {
|
|
|
|
|
OnHighMemory(lock);
|
|
|
|
|
if (success) {
|
|
|
|
|
bool lowMemory = IsVirtualMemoryLow(stat) || IsCommitSpaceLow(stat);
|
|
|
|
|
|
|
|
|
|
if (lowMemory) {
|
|
|
|
|
SendMemoryPressureEvent();
|
|
|
|
|
} else {
|
|
|
|
|
MaybeSendMemoryPressureStopEvent();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (lowMemory) {
|
|
|
|
|
MaybeSaveMemoryReport();
|
|
|
|
|
} else {
|
|
|
|
|
mSavedReport = false; // Save a new report if memory gets low again
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AdjustPollingInterval(lowMemory);
|
|
|
|
|
mUnderMemoryPressure = lowMemory;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
@ -291,14 +242,13 @@ nsAvailableMemoryWatcher::Notify(nsITimer* aTimer) {
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
nsAvailableMemoryWatcher::Observe(nsISupports* aSubject, const char* aTopic,
|
|
|
|
|
const char16_t* aData) {
|
|
|
|
|
MutexAutoLock lock(mMutex);
|
|
|
|
|
|
|
|
|
|
if (strcmp(aTopic, "quit-application") == 0) {
|
|
|
|
|
Shutdown(lock);
|
|
|
|
|
Shutdown();
|
|
|
|
|
} else if (strcmp(aTopic, "user-interaction-inactive") == 0) {
|
|
|
|
|
OnUserIdle(lock);
|
|
|
|
|
mTimer->Cancel();
|
|
|
|
|
} else if (strcmp(aTopic, "user-interaction-active") == 0) {
|
|
|
|
|
OnUserInteracting(lock);
|
|
|
|
|
mTimer->InitWithCallback(this, kPollingIntervalMS,
|
|
|
|
|
nsITimer::TYPE_REPEATING_SLACK);
|
|
|
|
|
} else {
|
|
|
|
|
MOZ_ASSERT_UNREACHABLE("Unknown topic");
|
|
|
|
|
}
|
|
|
|
@ -306,8 +256,12 @@ nsAvailableMemoryWatcher::Observe(nsISupports* aSubject, const char* aTopic,
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int64_t LowMemoryEventsPhysicalDistinguishedAmount() {
|
|
|
|
|
return sNumLowPhysicalMemEvents;
|
|
|
|
|
static int64_t LowMemoryEventsVirtualDistinguishedAmount() {
|
|
|
|
|
return sNumLowVirtualMemEvents;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int64_t LowMemoryEventsCommitSpaceDistinguishedAmount() {
|
|
|
|
|
return sNumLowCommitSpaceEvents;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class LowEventsReporter final : public nsIMemoryReporter {
|
|
|
|
@ -320,12 +274,22 @@ class LowEventsReporter final : public nsIMemoryReporter {
|
|
|
|
|
nsISupports* aData, bool aAnonymize) override {
|
|
|
|
|
// clang-format off
|
|
|
|
|
MOZ_COLLECT_REPORT(
|
|
|
|
|
"low-memory-events/physical", KIND_OTHER, UNITS_COUNT_CUMULATIVE,
|
|
|
|
|
LowMemoryEventsPhysicalDistinguishedAmount(),
|
|
|
|
|
"Number of low-physical-memory events fired since startup. We fire such an "
|
|
|
|
|
"event when a windows low memory resource notification is signaled. The "
|
|
|
|
|
"machine will start to page if it runs out of physical memory. This may "
|
|
|
|
|
"cause it to run slowly, but it shouldn't cause it to crash.");
|
|
|
|
|
"low-memory-events/virtual", KIND_OTHER, UNITS_COUNT_CUMULATIVE,
|
|
|
|
|
LowMemoryEventsVirtualDistinguishedAmount(),
|
|
|
|
|
"Number of low-virtual-memory events fired since startup. We fire such an "
|
|
|
|
|
"event if we notice there is less than predefined amount of virtual address "
|
|
|
|
|
"space available (if zero, this behavior is disabled, see "
|
|
|
|
|
"xpcom/base/AvailableMemoryTracker.cpp). The process will probably crash if "
|
|
|
|
|
"it runs out of virtual address space, so this event is dire.");
|
|
|
|
|
|
|
|
|
|
MOZ_COLLECT_REPORT(
|
|
|
|
|
"low-memory-events/commit-space", KIND_OTHER, UNITS_COUNT_CUMULATIVE,
|
|
|
|
|
LowMemoryEventsCommitSpaceDistinguishedAmount(),
|
|
|
|
|
"Number of low-commit-space events fired since startup. We fire such an "
|
|
|
|
|
"event if we notice there is less than a predefined amount of commit space "
|
|
|
|
|
"available (if zero, this behavior is disabled, see "
|
|
|
|
|
"xpcom/base/AvailableMemoryTracker.cpp). Windows will likely kill the process "
|
|
|
|
|
"if it runs out of commit space, so this event is dire.");
|
|
|
|
|
// clang-format on
|
|
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
@ -441,8 +405,11 @@ void Init() {
|
|
|
|
|
watcher->Init();
|
|
|
|
|
|
|
|
|
|
#if defined(XP_WIN)
|
|
|
|
|
RegisterLowMemoryEventsPhysicalDistinguishedAmount(
|
|
|
|
|
LowMemoryEventsPhysicalDistinguishedAmount);
|
|
|
|
|
RegisterStrongMemoryReporter(new LowEventsReporter());
|
|
|
|
|
RegisterLowMemoryEventsVirtualDistinguishedAmount(
|
|
|
|
|
LowMemoryEventsVirtualDistinguishedAmount);
|
|
|
|
|
RegisterLowMemoryEventsCommitSpaceDistinguishedAmount(
|
|
|
|
|
LowMemoryEventsCommitSpaceDistinguishedAmount);
|
|
|
|
|
|
|
|
|
|
if (XRE_IsParentProcess()) {
|
|
|
|
|
RefPtr<nsAvailableMemoryWatcher> poller = new nsAvailableMemoryWatcher();
|
|
|
|
|