Bug 624549, Don't call GC so aggressively in nsJSContext::CC, r=gal, a=jst

This commit is contained in:
Olli Pettay 2011-01-29 22:55:39 +02:00
parent 1d93af5cdb
commit 36fb03d5e8
4 changed files with 51 additions and 43 deletions

View File

@ -655,7 +655,7 @@ nsDOMWindowUtils::GarbageCollect(nsICycleCollectorListener *aListener)
}
#endif
nsJSContext::CC(aListener);
nsJSContext::CC(aListener, PR_TRUE);
return NS_OK;
}

View File

@ -161,14 +161,16 @@ static PRLogModuleInfo* gJSDiagnostics;
#define NS_MIN_CC_INTERVAL 10000 // ms
// If previous cycle collection collected more than this number of objects,
// the next collection will happen somewhat soon.
// Also, if there are more than this number suspected objects, GC will be called
// right before CC, if it wasn't called after last CC.
#define NS_COLLECTED_OBJECTS_LIMIT 5000
// CC will be called if GC has been called at least this number of times and
// there are at least NS_MIN_SUSPECT_CHANGES new suspected objects.
#define NS_MAX_GC_COUNT 5
#define NS_MIN_SUSPECT_CHANGES 10
#define NS_MIN_SUSPECT_CHANGES 100
// CC will be called if there are at least NS_MAX_SUSPECT_CHANGES new suspected
// objects.
#define NS_MAX_SUSPECT_CHANGES 100
#define NS_MAX_SUSPECT_CHANGES 1000
// if you add statics here, add them to the list in nsJSRuntime::Startup
@ -259,7 +261,7 @@ nsUserActivityObserver::Observe(nsISupports* aSubject, const char* aTopic,
if (sUserIsActive) {
sUserIsActive = PR_FALSE;
if (!sGCTimer) {
nsJSContext::IntervalCC();
nsJSContext::MaybeCC(PR_FALSE);
return NS_OK;
}
}
@ -299,7 +301,7 @@ NS_IMETHODIMP
nsCCMemoryPressureObserver::Observe(nsISupports* aSubject, const char* aTopic,
const PRUnichar* aData)
{
nsJSContext::CC(nsnull);
nsJSContext::CC(nsnull, PR_TRUE);
return NS_OK;
}
@ -3366,37 +3368,6 @@ nsJSContext::ScriptExecuted()
return NS_OK;
}
//static
void
nsJSContext::CC(nsICycleCollectorListener *aListener)
{
NS_TIME_FUNCTION_MIN(1.0);
++sCCollectCount;
#ifdef DEBUG_smaug
printf("Will run cycle collector (%i), %lldms since previous.\n",
sCCollectCount, (PR_Now() - sPreviousCCTime) / PR_USEC_PER_MSEC);
#endif
sPreviousCCTime = PR_Now();
sDelayedCCollectCount = 0;
sCCSuspectChanges = 0;
// nsCycleCollector_collect() no longer forces a JS garbage collection,
// so we have to do it ourselves here.
if (nsContentUtils::XPConnect()) {
nsContentUtils::XPConnect()->GarbageCollect();
}
sCollectedObjectsCounts = nsCycleCollector_collect(aListener);
sCCSuspectedCount = nsCycleCollector_suspectedCount();
if (nsJSRuntime::sRuntime) {
sSavedGCCount = JS_GetGCParameter(nsJSRuntime::sRuntime, JSGC_NUMBER);
}
#ifdef DEBUG_smaug
printf("Collected %u objects, %u suspected objects, took %lldms\n",
sCollectedObjectsCounts, sCCSuspectedCount,
(PR_Now() - sPreviousCCTime) / PR_USEC_PER_MSEC);
#endif
}
static inline uint32
GetGCRunsSinceLastCC()
{
@ -3412,6 +3383,40 @@ GetGCRunsSinceLastCC()
sSavedGCCount;
}
//static
void
nsJSContext::CC(nsICycleCollectorListener *aListener, PRBool aForceGC)
{
NS_TIME_FUNCTION_MIN(1.0);
++sCCollectCount;
#ifdef DEBUG_smaug
printf("Will run cycle collector (%i), %lldms since previous.\n",
sCCollectCount, (PR_Now() - sPreviousCCTime) / PR_USEC_PER_MSEC);
#endif
sPreviousCCTime = PR_Now();
sDelayedCCollectCount = 0;
sCCSuspectChanges = 0;
// nsCycleCollector_collect() no longer forces a JS garbage collection,
// so we have to do it ourselves here.
if (nsContentUtils::XPConnect() &&
(aForceGC ||
(!GetGCRunsSinceLastCC() &&
sCCSuspectedCount > NS_COLLECTED_OBJECTS_LIMIT))) {
nsContentUtils::XPConnect()->GarbageCollect();
}
sCollectedObjectsCounts = nsCycleCollector_collect(aListener);
sCCSuspectedCount = nsCycleCollector_suspectedCount();
if (nsJSRuntime::sRuntime) {
sSavedGCCount = JS_GetGCParameter(nsJSRuntime::sRuntime, JSGC_NUMBER);
}
#ifdef DEBUG_smaug
printf("Collected %u objects, %u suspected objects, took %lldms\n",
sCollectedObjectsCounts, sCCSuspectedCount,
(PR_Now() - sPreviousCCTime) / PR_USEC_PER_MSEC);
#endif
}
//static
PRBool
nsJSContext::MaybeCC(PRBool aHigherProbability)
@ -3469,7 +3474,7 @@ nsJSContext::CCIfUserInactive()
if (sUserIsActive) {
MaybeCC(PR_TRUE);
} else {
IntervalCC();
IntervalCC(PR_TRUE);
}
}
@ -3484,11 +3489,11 @@ nsJSContext::MaybeCCIfUserInactive()
//static
PRBool
nsJSContext::IntervalCC()
nsJSContext::IntervalCC(PRBool aForceGC)
{
if ((PR_Now() - sPreviousCCTime) >=
PRTime(NS_MIN_CC_INTERVAL * PR_USEC_PER_MSEC)) {
nsJSContext::CC(nsnull);
nsJSContext::CC(nsnull, aForceGC);
return PR_TRUE;
}
#ifdef DEBUG_smaug

View File

@ -189,7 +189,8 @@ public:
// CC does always call cycle collector and it also updates the counters
// that MaybeCC uses.
static void CC(nsICycleCollectorListener *aListener);
static void CC(nsICycleCollectorListener *aListener,
PRBool aForceGC = PR_FALSE);
// MaybeCC calls cycle collector if certain conditions are fulfilled.
// The conditions are:
@ -208,9 +209,10 @@ public:
// IntervalCC() calls CC() if at least NS_MIN_CC_INTERVAL milliseconds have
// elapsed since the previous cycle collector call.
static PRBool IntervalCC();
static PRBool IntervalCC(PRBool aForceGC = PR_FALSE);
// Calls IntervalCC() if user is currently inactive, otherwise MaybeCC(PR_TRUE)
// Calls IntervalCC(PR_TRUE) if user is currently inactive,
// otherwise MaybeCC(PR_TRUE)
static void CCIfUserInactive();
static void MaybeCCIfUserInactive();

View File

@ -56,10 +56,11 @@ _CHROME_FILES = \
test_371798.xul \
test_342484.xul \
test_341972a.xul \
test_381357.xul \
test_favicon_annotations.xul \
$(NULL)
# test_381357.xul is disabled for now because of bug 561007. See also bug 624549.
libs:: $(_HTTP_FILES)
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)