зеркало из https://github.com/mozilla/gecko-dev.git
Bug 805855 - Free dirty pages in response to all memory-pressure messages. r=jlebar
This commit is contained in:
Родитель
f39e18e483
Коммит
fbc8afdb64
|
@ -587,3 +587,7 @@ pref("general.useragent.override.facebook.com", "\(Mobile#(Android; Mobile");
|
|||
pref("general.useragent.override.youtube.com", "\(Mobile#(Android; Mobile");
|
||||
|
||||
pref("jsloader.reuseGlobal", true);
|
||||
|
||||
// Enable freeing dirty pages when minimizing memory; this reduces memory
|
||||
// consumption when applications are sent to the background.
|
||||
pref("memory.free_dirty_pages", true);
|
||||
|
|
|
@ -3810,6 +3810,9 @@ pref("memory.low_memory_notification_interval_ms", 10000);
|
|||
// window to be collected via the GC/CC.
|
||||
pref("memory.ghost_window_timeout_seconds", 60);
|
||||
|
||||
// Disable freeing dirty pages when minimizing memory.
|
||||
pref("memory.free_dirty_pages", false);
|
||||
|
||||
pref("social.enabled", false);
|
||||
|
||||
// Disable idle observer fuzz, because only privileged content can access idle
|
||||
|
|
|
@ -5,22 +5,37 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/AvailableMemoryTracker.h"
|
||||
#include "nsThread.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "nsWindowsDllInterceptor.h"
|
||||
|
||||
#include "prinrval.h"
|
||||
#include "pratom.h"
|
||||
#include "prenv.h"
|
||||
|
||||
#include "nsIMemoryReporter.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsIRunnable.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include <windows.h>
|
||||
#include "nsThread.h"
|
||||
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/Services.h"
|
||||
|
||||
#if defined(XP_WIN)
|
||||
# include "nsWindowsDllInterceptor.h"
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
#if defined(MOZ_MEMORY)
|
||||
# include "jemalloc.h"
|
||||
#endif // MOZ_MEMORY
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
namespace {
|
||||
|
||||
#if defined(XP_WIN)
|
||||
|
||||
// We don't want our diagnostic functions to call malloc, because that could
|
||||
// call VirtualAlloc, and we'd end up back in here! So here are a few simple
|
||||
// debugging macros (modeled on jemalloc's), which hopefully won't allocate.
|
||||
|
@ -461,6 +476,86 @@ public:
|
|||
|
||||
NS_IMPL_ISUPPORTS1(NumLowPhysicalMemoryEventsMemoryReporter, nsIMemoryReporter)
|
||||
|
||||
#endif // defined(XP_WIN)
|
||||
|
||||
/**
|
||||
* This runnable is executed in response to a memory-pressure event; we spin
|
||||
* the event-loop when receiving the memory-pressure event in the hope that
|
||||
* other observers will synchronously free some memory that we'll be able to
|
||||
* purge here.
|
||||
*/
|
||||
class nsJemallocFreeDirtyPagesRunnable MOZ_FINAL : public nsIRunnable
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIRUNNABLE
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsJemallocFreeDirtyPagesRunnable, nsIRunnable)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsJemallocFreeDirtyPagesRunnable::Run()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
#if defined(MOZ_JEMALLOC)
|
||||
mallctl("arenas.purge", nullptr, 0, nullptr, 0);
|
||||
#elif defined(MOZ_MEMORY)
|
||||
jemalloc_free_dirty_pages();
|
||||
#endif
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* The memory pressure watcher is used for listening to memory-pressure events
|
||||
* and reacting upon them. We use one instance per process currently only for
|
||||
* cleaning up dirty unused pages held by jemalloc.
|
||||
*/
|
||||
class nsMemoryPressureWatcher MOZ_FINAL : public nsIObserver
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
void Init();
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsMemoryPressureWatcher, nsIObserver)
|
||||
|
||||
/**
|
||||
* Initialize and subscribe to the memory-pressure events. We subscribe to the
|
||||
* observer service in this method and not in the constructor because we need
|
||||
* to hold a strong reference to 'this' before calling the observer service.
|
||||
*/
|
||||
void
|
||||
nsMemoryPressureWatcher::Init()
|
||||
{
|
||||
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
|
||||
|
||||
if (os) {
|
||||
os->AddObserver(this, "memory-pressure", /* ownsWeak */ false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reacts to all types of memory-pressure events, launches a runnable to
|
||||
* free dirty pages held by jemalloc.
|
||||
* @see nsMemoryPressureWatcher::FreeDirtyPages
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
nsMemoryPressureWatcher::Observe(nsISupports *subject, const char *topic,
|
||||
const PRUnichar *data)
|
||||
{
|
||||
MOZ_ASSERT(!strcmp(topic, "memory-pressure"), "Unknown topic");
|
||||
|
||||
nsRefPtr<nsIRunnable> runnable = new nsJemallocFreeDirtyPagesRunnable();
|
||||
|
||||
NS_DispatchToMainThread(runnable);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -468,7 +563,7 @@ namespace AvailableMemoryTracker {
|
|||
|
||||
void Activate()
|
||||
{
|
||||
#if defined(_M_IX86)
|
||||
#if defined(_M_IX86) && defined(XP_WIN)
|
||||
MOZ_ASSERT(sInitialized);
|
||||
MOZ_ASSERT(!sHooksActive);
|
||||
|
||||
|
@ -496,6 +591,12 @@ void Activate()
|
|||
}
|
||||
sHooksActive = true;
|
||||
#endif
|
||||
|
||||
if (Preferences::GetBool("memory.free_dirty_pages", false)) {
|
||||
// This object is held alive by the observer service.
|
||||
nsRefPtr<nsMemoryPressureWatcher> watcher = new nsMemoryPressureWatcher();
|
||||
watcher->Init();
|
||||
}
|
||||
}
|
||||
|
||||
void Init()
|
||||
|
@ -509,7 +610,7 @@ void Init()
|
|||
// process, because we aren't going to run out of virtual memory, and the
|
||||
// system is likely to have a fair bit of physical memory.
|
||||
|
||||
#if defined(_M_IX86)
|
||||
#if defined(_M_IX86) && defined(XP_WIN)
|
||||
// Don't register the hooks if we're a build instrumented for PGO: If we're
|
||||
// an instrumented build, the compiler adds function calls all over the place
|
||||
// which may call VirtualAlloc; this makes it hard to prevent
|
||||
|
|
|
@ -10,10 +10,9 @@
|
|||
namespace mozilla {
|
||||
namespace AvailableMemoryTracker {
|
||||
|
||||
// The AvailableMemoryTracker is implemented only on Windows. But to make
|
||||
// callers' lives easier, we stub out empty calls for all its public functions.
|
||||
// So you can always initialize the AvailableMemoryTracker; it just might not
|
||||
// do anything.
|
||||
// The AvailableMemoryTracker launches a memory pressure watcher on all
|
||||
// platforms to react to low-memory situations and on Windows it implements
|
||||
// the full functionality used to monitor how much memory is available.
|
||||
//
|
||||
// Init() must be called before any other threads have started, because it
|
||||
// modifies the in-memory implementations of some DLL functions in
|
||||
|
@ -22,13 +21,8 @@ namespace AvailableMemoryTracker {
|
|||
// The hooks don't do anything until Activate() is called. It's an error to
|
||||
// call Activate() without first calling Init().
|
||||
|
||||
#if defined(XP_WIN)
|
||||
void Init();
|
||||
void Activate();
|
||||
#else
|
||||
void Init() {}
|
||||
void Activate() {}
|
||||
#endif
|
||||
|
||||
} // namespace AvailableMemoryTracker
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -43,6 +43,7 @@ CPPSRCS = \
|
|||
nsGZFileWriter.cpp \
|
||||
nsMemoryInfoDumper.cpp \
|
||||
nsMessageLoop.cpp \
|
||||
AvailableMemoryTracker.cpp \
|
||||
$(NULL)
|
||||
|
||||
ifeq ($(OS_ARCH),Linux)
|
||||
|
@ -93,8 +94,6 @@ CSRCS += pure_api.c
|
|||
EXPORTS += pure.h
|
||||
endif
|
||||
|
||||
CPPSRCS += AvailableMemoryTracker.cpp
|
||||
|
||||
endif #if OS_ARCH == WINNT
|
||||
|
||||
SDK_XPIDLSRCS = \
|
||||
|
|
Загрузка…
Ссылка в новой задаче