зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1130439 - Trigger compacting GCs after the user becomes inactive r=smaug r=terrence
This commit is contained in:
Родитель
2c936db8ea
Коммит
2b3e9874b8
|
@ -107,6 +107,10 @@ const size_t gStackSize = 8192;
|
||||||
|
|
||||||
#define NS_FULL_GC_DELAY 60000 // ms
|
#define NS_FULL_GC_DELAY 60000 // ms
|
||||||
|
|
||||||
|
// The amount of time to wait from the user being idle to starting a shrinking
|
||||||
|
// GC.
|
||||||
|
#define NS_SHRINKING_GC_DELAY 15000 // ms
|
||||||
|
|
||||||
// Maximum amount of time that should elapse between incremental GC slices
|
// Maximum amount of time that should elapse between incremental GC slices
|
||||||
#define NS_INTERSLICE_GC_DELAY 100 // ms
|
#define NS_INTERSLICE_GC_DELAY 100 // ms
|
||||||
|
|
||||||
|
@ -148,6 +152,7 @@ static const uint32_t kMaxICCDuration = 2000; // ms
|
||||||
|
|
||||||
static nsITimer *sGCTimer;
|
static nsITimer *sGCTimer;
|
||||||
static nsITimer *sShrinkGCBuffersTimer;
|
static nsITimer *sShrinkGCBuffersTimer;
|
||||||
|
static nsITimer *sShrinkingGCTimer;
|
||||||
static nsITimer *sCCTimer;
|
static nsITimer *sCCTimer;
|
||||||
static nsITimer *sICCTimer;
|
static nsITimer *sICCTimer;
|
||||||
static nsITimer *sFullGCTimer;
|
static nsITimer *sFullGCTimer;
|
||||||
|
@ -212,6 +217,7 @@ static nsIScriptSecurityManager *sSecurityManager;
|
||||||
// the appropriate pref is set.
|
// the appropriate pref is set.
|
||||||
|
|
||||||
static bool sGCOnMemoryPressure;
|
static bool sGCOnMemoryPressure;
|
||||||
|
static bool sCompactOnUserInactive;
|
||||||
|
|
||||||
// In testing, we call RunNextCollectorTimer() to ensure that the collectors are run more
|
// In testing, we call RunNextCollectorTimer() to ensure that the collectors are run more
|
||||||
// aggressively than they would be in regular browsing. sExpensiveCollectorPokes keeps
|
// aggressively than they would be in regular browsing. sExpensiveCollectorPokes keeps
|
||||||
|
@ -234,6 +240,7 @@ static void
|
||||||
KillTimers()
|
KillTimers()
|
||||||
{
|
{
|
||||||
nsJSContext::KillGCTimer();
|
nsJSContext::KillGCTimer();
|
||||||
|
nsJSContext::KillShrinkingGCTimer();
|
||||||
nsJSContext::KillShrinkGCBuffersTimer();
|
nsJSContext::KillShrinkGCBuffersTimer();
|
||||||
nsJSContext::KillCCTimer();
|
nsJSContext::KillCCTimer();
|
||||||
nsJSContext::KillICCTimer();
|
nsJSContext::KillICCTimer();
|
||||||
|
@ -266,22 +273,30 @@ NS_IMETHODIMP
|
||||||
nsJSEnvironmentObserver::Observe(nsISupports* aSubject, const char* aTopic,
|
nsJSEnvironmentObserver::Observe(nsISupports* aSubject, const char* aTopic,
|
||||||
const char16_t* aData)
|
const char16_t* aData)
|
||||||
{
|
{
|
||||||
if (sGCOnMemoryPressure && !nsCRT::strcmp(aTopic, "memory-pressure")) {
|
if (!nsCRT::strcmp(aTopic, "memory-pressure")) {
|
||||||
if(StringBeginsWith(nsDependentString(aData),
|
if (sGCOnMemoryPressure) {
|
||||||
NS_LITERAL_STRING("low-memory-ongoing"))) {
|
if(StringBeginsWith(nsDependentString(aData),
|
||||||
// Don't GC/CC if we are in an ongoing low-memory state since its very
|
NS_LITERAL_STRING("low-memory-ongoing"))) {
|
||||||
// slow and it likely won't help us anyway.
|
// Don't GC/CC if we are in an ongoing low-memory state since its very
|
||||||
return NS_OK;
|
// slow and it likely won't help us anyway.
|
||||||
}
|
return NS_OK;
|
||||||
nsJSContext::GarbageCollectNow(JS::gcreason::MEM_PRESSURE,
|
}
|
||||||
nsJSContext::NonIncrementalGC,
|
|
||||||
nsJSContext::ShrinkingGC);
|
|
||||||
nsJSContext::CycleCollectNow();
|
|
||||||
if (NeedsGCAfterCC()) {
|
|
||||||
nsJSContext::GarbageCollectNow(JS::gcreason::MEM_PRESSURE,
|
nsJSContext::GarbageCollectNow(JS::gcreason::MEM_PRESSURE,
|
||||||
nsJSContext::NonIncrementalGC,
|
nsJSContext::NonIncrementalGC,
|
||||||
nsJSContext::ShrinkingGC);
|
nsJSContext::ShrinkingGC);
|
||||||
|
nsJSContext::CycleCollectNow();
|
||||||
|
if (NeedsGCAfterCC()) {
|
||||||
|
nsJSContext::GarbageCollectNow(JS::gcreason::MEM_PRESSURE,
|
||||||
|
nsJSContext::NonIncrementalGC,
|
||||||
|
nsJSContext::ShrinkingGC);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} else if (!nsCRT::strcmp(aTopic, "user-interaction-inactive")) {
|
||||||
|
if (sCompactOnUserInactive) {
|
||||||
|
nsJSContext::PokeShrinkingGC();
|
||||||
|
}
|
||||||
|
} else if (!nsCRT::strcmp(aTopic, "user-interaction-active")) {
|
||||||
|
nsJSContext::KillShrinkingGCTimer();
|
||||||
} else if (!nsCRT::strcmp(aTopic, "quit-application") ||
|
} else if (!nsCRT::strcmp(aTopic, "quit-application") ||
|
||||||
!nsCRT::strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
|
!nsCRT::strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
|
||||||
sShuttingDown = true;
|
sShuttingDown = true;
|
||||||
|
@ -1284,12 +1299,11 @@ nsJSContext::GarbageCollectNow(JS::gcreason::Reason aReason,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JSGCInvocationKind gckind = aShrinking == ShrinkingGC ? GC_SHRINK : GC_NORMAL;
|
||||||
JS::PrepareForFullGC(sRuntime);
|
JS::PrepareForFullGC(sRuntime);
|
||||||
if (aIncremental == IncrementalGC) {
|
if (aIncremental == IncrementalGC) {
|
||||||
MOZ_ASSERT(aShrinking == NonShrinkingGC);
|
JS::StartIncrementalGC(sRuntime, gckind, aReason, aSliceMillis);
|
||||||
JS::StartIncrementalGC(sRuntime, GC_NORMAL, aReason, aSliceMillis);
|
|
||||||
} else {
|
} else {
|
||||||
JSGCInvocationKind gckind = aShrinking == ShrinkingGC ? GC_SHRINK : GC_NORMAL;
|
|
||||||
JS::GCForReason(sRuntime, gckind, aReason);
|
JS::GCForReason(sRuntime, gckind, aReason);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1798,6 +1812,16 @@ ShrinkGCBuffersTimerFired(nsITimer *aTimer, void *aClosure)
|
||||||
nsJSContext::ShrinkGCBuffersNow();
|
nsJSContext::ShrinkGCBuffersNow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
void
|
||||||
|
ShrinkingGCTimerFired(nsITimer* aTimer, void* aClosure)
|
||||||
|
{
|
||||||
|
nsJSContext::KillShrinkingGCTimer();
|
||||||
|
nsJSContext::GarbageCollectNow(JS::gcreason::USER_INACTIVE,
|
||||||
|
nsJSContext::IncrementalGC,
|
||||||
|
nsJSContext::ShrinkingGC);
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
ShouldTriggerCC(uint32_t aSuspected)
|
ShouldTriggerCC(uint32_t aSuspected)
|
||||||
{
|
{
|
||||||
|
@ -2030,6 +2054,26 @@ nsJSContext::PokeShrinkGCBuffers()
|
||||||
nsITimer::TYPE_ONE_SHOT);
|
nsITimer::TYPE_ONE_SHOT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
void
|
||||||
|
nsJSContext::PokeShrinkingGC()
|
||||||
|
{
|
||||||
|
if (sShrinkingGCTimer || sShuttingDown) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CallCreateInstance("@mozilla.org/timer;1", &sShrinkingGCTimer);
|
||||||
|
|
||||||
|
if (!sShrinkingGCTimer) {
|
||||||
|
// Failed to create timer (probably because we're in XPCOM shutdown)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sShrinkingGCTimer->InitWithFuncCallback(ShrinkingGCTimerFired, nullptr,
|
||||||
|
NS_SHRINKING_GC_DELAY,
|
||||||
|
nsITimer::TYPE_ONE_SHOT);
|
||||||
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
void
|
void
|
||||||
nsJSContext::MaybePokeCC()
|
nsJSContext::MaybePokeCC()
|
||||||
|
@ -2091,6 +2135,16 @@ nsJSContext::KillShrinkGCBuffersTimer()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//static
|
||||||
|
void
|
||||||
|
nsJSContext::KillShrinkingGCTimer()
|
||||||
|
{
|
||||||
|
if (sShrinkingGCTimer) {
|
||||||
|
sShrinkingGCTimer->Cancel();
|
||||||
|
NS_RELEASE(sShrinkingGCTimer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//static
|
//static
|
||||||
void
|
void
|
||||||
nsJSContext::KillCCTimer()
|
nsJSContext::KillCCTimer()
|
||||||
|
@ -2282,7 +2336,7 @@ void
|
||||||
mozilla::dom::StartupJSEnvironment()
|
mozilla::dom::StartupJSEnvironment()
|
||||||
{
|
{
|
||||||
// initialize all our statics, so that we can restart XPCOM
|
// initialize all our statics, so that we can restart XPCOM
|
||||||
sGCTimer = sFullGCTimer = sCCTimer = sICCTimer = nullptr;
|
sGCTimer = sShrinkingGCTimer = sFullGCTimer = sCCTimer = sICCTimer = nullptr;
|
||||||
sCCLockedOut = false;
|
sCCLockedOut = false;
|
||||||
sCCLockedOutTime = 0;
|
sCCLockedOutTime = 0;
|
||||||
sLastCCEndTime = TimeStamp();
|
sLastCCEndTime = TimeStamp();
|
||||||
|
@ -2687,8 +2741,14 @@ nsJSContext::EnsureStatics()
|
||||||
"javascript.options.gc_on_memory_pressure",
|
"javascript.options.gc_on_memory_pressure",
|
||||||
true);
|
true);
|
||||||
|
|
||||||
|
Preferences::AddBoolVarCache(&sCompactOnUserInactive,
|
||||||
|
"javascript.options.compact_on_user_inactive",
|
||||||
|
true);
|
||||||
|
|
||||||
nsIObserver* observer = new nsJSEnvironmentObserver();
|
nsIObserver* observer = new nsJSEnvironmentObserver();
|
||||||
obs->AddObserver(observer, "memory-pressure", false);
|
obs->AddObserver(observer, "memory-pressure", false);
|
||||||
|
obs->AddObserver(observer, "user-interaction-inactive", false);
|
||||||
|
obs->AddObserver(observer, "user-interaction-active", false);
|
||||||
obs->AddObserver(observer, "quit-application", false);
|
obs->AddObserver(observer, "quit-application", false);
|
||||||
obs->AddObserver(observer, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
|
obs->AddObserver(observer, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
|
||||||
|
|
||||||
|
|
|
@ -116,6 +116,9 @@ public:
|
||||||
static void PokeShrinkGCBuffers();
|
static void PokeShrinkGCBuffers();
|
||||||
static void KillShrinkGCBuffersTimer();
|
static void KillShrinkGCBuffersTimer();
|
||||||
|
|
||||||
|
static void PokeShrinkingGC();
|
||||||
|
static void KillShrinkingGCTimer();
|
||||||
|
|
||||||
static void MaybePokeCC();
|
static void MaybePokeCC();
|
||||||
static void KillCCTimer();
|
static void KillCCTimer();
|
||||||
static void KillICCTimer();
|
static void KillICCTimer();
|
||||||
|
|
|
@ -99,7 +99,8 @@ namespace JS {
|
||||||
D(REFRESH_FRAME) \
|
D(REFRESH_FRAME) \
|
||||||
D(FULL_GC_TIMER) \
|
D(FULL_GC_TIMER) \
|
||||||
D(SHUTDOWN_CC) \
|
D(SHUTDOWN_CC) \
|
||||||
D(FINISH_LARGE_EVALUATE)
|
D(FINISH_LARGE_EVALUATE) \
|
||||||
|
D(USER_INACTIVE)
|
||||||
|
|
||||||
namespace gcreason {
|
namespace gcreason {
|
||||||
|
|
||||||
|
|
|
@ -364,7 +364,9 @@ js::AssertSameCompartment(JSObject *objA, JSObject *objB)
|
||||||
JS_FRIEND_API(void)
|
JS_FRIEND_API(void)
|
||||||
js::NotifyAnimationActivity(JSObject *obj)
|
js::NotifyAnimationActivity(JSObject *obj)
|
||||||
{
|
{
|
||||||
obj->compartment()->lastAnimationTime = PRMJ_Now();
|
int64_t timeNow = PRMJ_Now();
|
||||||
|
obj->compartment()->lastAnimationTime = timeNow;
|
||||||
|
obj->runtimeFromMainThread()->lastAnimationTime = timeNow;
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_FRIEND_API(uint32_t)
|
JS_FRIEND_API(uint32_t)
|
||||||
|
|
|
@ -1888,7 +1888,10 @@ ArenaLists::allocateFromArenaInner(JS::Zone *zone, ArenaHeader *aheader, AllocKi
|
||||||
bool
|
bool
|
||||||
GCRuntime::shouldCompact()
|
GCRuntime::shouldCompact()
|
||||||
{
|
{
|
||||||
return invocationKind == GC_SHRINK && isCompactingGCEnabled();
|
// Compact on shrinking GC if enabled, but skip compacting in incremental
|
||||||
|
// GCs if we are currently animating.
|
||||||
|
return invocationKind == GC_SHRINK && isCompactingGCEnabled() &&
|
||||||
|
(!isIncremental || rt->lastAnimationTime + PRMJ_USEC_PER_SEC < PRMJ_Now());
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -212,7 +212,8 @@ JSRuntime::JSRuntime(JSRuntime *parentRuntime)
|
||||||
#endif
|
#endif
|
||||||
largeAllocationFailureCallback(nullptr),
|
largeAllocationFailureCallback(nullptr),
|
||||||
oomCallback(nullptr),
|
oomCallback(nullptr),
|
||||||
debuggerMallocSizeOf(ReturnZeroSize)
|
debuggerMallocSizeOf(ReturnZeroSize),
|
||||||
|
lastAnimationTime(0)
|
||||||
{
|
{
|
||||||
setGCStoreBufferPtr(&gc.storeBuffer);
|
setGCStoreBufferPtr(&gc.storeBuffer);
|
||||||
|
|
||||||
|
|
|
@ -1417,6 +1417,9 @@ struct JSRuntime : public JS::shadow::Runtime,
|
||||||
* function to assess the size of malloc'd blocks of memory.
|
* function to assess the size of malloc'd blocks of memory.
|
||||||
*/
|
*/
|
||||||
mozilla::MallocSizeOf debuggerMallocSizeOf;
|
mozilla::MallocSizeOf debuggerMallocSizeOf;
|
||||||
|
|
||||||
|
/* Last time at which an animation was played for this runtime. */
|
||||||
|
int64_t lastAnimationTime;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
|
|
|
@ -1081,6 +1081,7 @@ pref("javascript.options.mem.gc_compacting", true);
|
||||||
pref("javascript.options.mem.log", false);
|
pref("javascript.options.mem.log", false);
|
||||||
pref("javascript.options.mem.notify", false);
|
pref("javascript.options.mem.notify", false);
|
||||||
pref("javascript.options.gc_on_memory_pressure", true);
|
pref("javascript.options.gc_on_memory_pressure", true);
|
||||||
|
pref("javascript.options.compact_on_user_inactive", true);
|
||||||
|
|
||||||
pref("javascript.options.mem.gc_high_frequency_time_limit_ms", 1000);
|
pref("javascript.options.mem.gc_high_frequency_time_limit_ms", 1000);
|
||||||
pref("javascript.options.mem.gc_high_frequency_low_limit_mb", 100);
|
pref("javascript.options.mem.gc_high_frequency_low_limit_mb", 100);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче