зеркало из https://github.com/mozilla/pjs.git
Bug 415025, try to improve CC scheduling, r=peterv, sr=jst
This commit is contained in:
Родитель
35a7722e32
Коммит
97ccc330e6
|
@ -160,6 +160,16 @@ static PRLogModuleInfo* gJSDiagnostics;
|
|||
#define NS_PROBABILITY_MULTIPLIER 3
|
||||
// Cycle collector should never run more often than this value
|
||||
#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.
|
||||
#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
|
||||
// CC will be called if there are at least NS_MAX_SUSPECT_CHANGES new suspected
|
||||
// objects.
|
||||
#define NS_MAX_SUSPECT_CHANGES 100
|
||||
|
||||
// if you add statics here, add them to the list in nsJSRuntime::Startup
|
||||
|
||||
|
@ -167,7 +177,10 @@ static PRUint32 sDelayedCCollectCount;
|
|||
static PRUint32 sCCollectCount;
|
||||
static PRBool sUserIsActive;
|
||||
static PRTime sPreviousCCTime;
|
||||
static PRBool sPreviousCCDidCollect;
|
||||
static PRUint32 sCollectedObjectsCounts;
|
||||
static PRUint32 sGCCount;
|
||||
static PRUint32 sCCSuspectChanges;
|
||||
static PRUint32 sCCSuspectedCount;
|
||||
static nsITimer *sGCTimer;
|
||||
static PRBool sReadyForGC;
|
||||
|
||||
|
@ -839,6 +852,7 @@ MaybeGC(JSContext *cx)
|
|||
|| cx->runtime->gcZeal > 0
|
||||
#endif
|
||||
) {
|
||||
++sGCCount;
|
||||
JS_GC(cx);
|
||||
}
|
||||
}
|
||||
|
@ -3317,19 +3331,22 @@ nsJSContext::PreserveWrapper(nsIXPConnectWrappedNative *aWrapper)
|
|||
void
|
||||
nsJSContext::CC()
|
||||
{
|
||||
sPreviousCCTime = PR_Now();
|
||||
sDelayedCCollectCount = 0;
|
||||
++sCCollectCount;
|
||||
#ifdef DEBUG_smaug
|
||||
printf("Will run cycle collector (%i)\n", sCCollectCount);
|
||||
printf("Will run cycle collector (%i), %lldms since previous.\n",
|
||||
sCCollectCount, (PR_Now() - sPreviousCCTime) / PR_USEC_PER_MSEC);
|
||||
#endif
|
||||
sPreviousCCTime = PR_Now();
|
||||
sDelayedCCollectCount = 0;
|
||||
sGCCount = 0;
|
||||
sCCSuspectChanges = 0;
|
||||
// nsCycleCollector_collect() will run a ::JS_GC() indirectly, so
|
||||
// we do not explicitly call ::JS_GC() here.
|
||||
sPreviousCCDidCollect = nsCycleCollector_collect();
|
||||
sCollectedObjectsCounts = nsCycleCollector_collect();
|
||||
sCCSuspectedCount = nsCycleCollector_suspectedCount();
|
||||
#ifdef DEBUG_smaug
|
||||
printf("(1) %s\n", sPreviousCCDidCollect ?
|
||||
"Cycle collector did collect nodes" :
|
||||
"Cycle collector did not collect nodes");
|
||||
printf("Collected %u objects, %u suspected objects\n",
|
||||
sCollectedObjectsCounts, sCCSuspectedCount);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -3338,13 +3355,42 @@ PRBool
|
|||
nsJSContext::MaybeCC(PRBool aHigherProbability)
|
||||
{
|
||||
++sDelayedCCollectCount;
|
||||
|
||||
// Don't check suspected count if CC will be called anyway.
|
||||
if (sCCSuspectChanges <= NS_MIN_SUSPECT_CHANGES ||
|
||||
sGCCount <= NS_MAX_GC_COUNT) {
|
||||
#ifdef DEBUG_smaug
|
||||
PRTime now = PR_Now();
|
||||
#endif
|
||||
PRUint32 suspected = nsCycleCollector_suspectedCount();
|
||||
#ifdef DEBUG_smaug
|
||||
printf("%u suspected objects (%lldms), sCCSuspectedCount %u\n",
|
||||
suspected, (PR_Now() - now) / PR_USEC_PER_MSEC,
|
||||
sCCSuspectedCount);
|
||||
#endif
|
||||
// Update only when suspected count has increased.
|
||||
if (suspected > sCCSuspectedCount) {
|
||||
sCCSuspectChanges += (suspected - sCCSuspectedCount);
|
||||
sCCSuspectedCount = suspected;
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG_smaug
|
||||
printf("sCCSuspectChanges %u, sGCCount %u\n",
|
||||
sCCSuspectChanges, sGCCount);
|
||||
#endif
|
||||
|
||||
// Increase the probability also if the previous call to cycle collector
|
||||
// collected something.
|
||||
if (aHigherProbability || sPreviousCCDidCollect) {
|
||||
if (aHigherProbability ||
|
||||
sCollectedObjectsCounts > NS_COLLECTED_OBJECTS_LIMIT) {
|
||||
sDelayedCCollectCount *= NS_PROBABILITY_MULTIPLIER;
|
||||
}
|
||||
|
||||
if (!sGCTimer && (sDelayedCCollectCount > NS_MAX_DELAYED_CCOLLECT)) {
|
||||
if (!sGCTimer &&
|
||||
(sDelayedCCollectCount > NS_MAX_DELAYED_CCOLLECT) &&
|
||||
((sCCSuspectChanges > NS_MIN_SUSPECT_CHANGES &&
|
||||
sGCCount > NS_MAX_GC_COUNT) ||
|
||||
(sCCSuspectChanges > NS_MAX_SUSPECT_CHANGES))) {
|
||||
if ((PR_Now() - sPreviousCCTime) >=
|
||||
PRTime(NS_MIN_CC_INTERVAL * PR_USEC_PER_MSEC)) {
|
||||
nsJSContext::CC();
|
||||
|
@ -3559,7 +3605,10 @@ nsJSRuntime::Startup()
|
|||
sCCollectCount = 0;
|
||||
sUserIsActive = PR_FALSE;
|
||||
sPreviousCCTime = 0;
|
||||
sPreviousCCDidCollect = PR_FALSE;
|
||||
sCollectedObjectsCounts = 0;
|
||||
sGCCount = 0;
|
||||
sCCSuspectChanges = 0;
|
||||
sCCSuspectedCount = 0;
|
||||
sGCTimer = nsnull;
|
||||
sReadyForGC = PR_FALSE;
|
||||
sLoadInProgressGCTimer = PR_FALSE;
|
||||
|
|
|
@ -763,6 +763,17 @@ struct nsPurpleBuffer
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
PRUint32 Count()
|
||||
{
|
||||
PRUint32 count = mBackingStore.Count();
|
||||
for (PRUint32 i = 0; i < N_POINTERS; ++i) {
|
||||
if (mCache[i]) {
|
||||
++count;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
};
|
||||
|
||||
static PR_CALLBACK PLDHashOperator
|
||||
|
@ -867,6 +878,7 @@ struct nsCycleCollector
|
|||
PRBool mCollectionInProgress;
|
||||
PRBool mScanInProgress;
|
||||
PRBool mFollowupCollection;
|
||||
PRUint32 mCollectedObjects;
|
||||
|
||||
nsCycleCollectionLanguageRuntime *mRuntimes[nsIProgrammingLanguage::MAX+1];
|
||||
nsCycleCollectionXPCOMRuntime mXPCOMRuntime;
|
||||
|
@ -895,9 +907,10 @@ struct nsCycleCollector
|
|||
|
||||
PRBool Suspect(nsISupports *n);
|
||||
PRBool Forget(nsISupports *n);
|
||||
PRBool Collect(PRUint32 aTryCollections = 1);
|
||||
PRUint32 Collect(PRUint32 aTryCollections = 1);
|
||||
PRBool BeginCollection();
|
||||
PRBool FinishCollection();
|
||||
PRUint32 SuspectedCount();
|
||||
void Shutdown();
|
||||
|
||||
void ClearGraph()
|
||||
|
@ -1613,6 +1626,7 @@ nsCycleCollector::CollectWhite()
|
|||
mStats.mFreedBytes += (ms1.lTotalCount - ms2.lTotalCount);
|
||||
#endif
|
||||
|
||||
mCollectedObjects += count;
|
||||
return count > 0;
|
||||
}
|
||||
|
||||
|
@ -1818,6 +1832,7 @@ InitMemHook(void)
|
|||
nsCycleCollector::nsCycleCollector() :
|
||||
mCollectionInProgress(PR_FALSE),
|
||||
mScanInProgress(PR_FALSE),
|
||||
mCollectedObjects(0),
|
||||
mWhiteNodes(nsnull),
|
||||
mWhiteNodeCount(0),
|
||||
#ifdef DEBUG_CC
|
||||
|
@ -2138,7 +2153,7 @@ nsCycleCollector::Freed(void *n)
|
|||
}
|
||||
#endif
|
||||
|
||||
PRBool
|
||||
PRUint32
|
||||
nsCycleCollector::Collect(PRUint32 aTryCollections)
|
||||
{
|
||||
#if defined(DEBUG_CC) && !defined(__MINGW32__)
|
||||
|
@ -2148,7 +2163,7 @@ nsCycleCollector::Collect(PRUint32 aTryCollections)
|
|||
|
||||
// This can legitimately happen in a few cases. See bug 383651.
|
||||
if (mCollectionInProgress)
|
||||
return PR_FALSE;
|
||||
return 0;
|
||||
|
||||
#ifdef COLLECT_TIME_DEBUG
|
||||
printf("cc: Starting nsCycleCollector::Collect(%d)\n", aTryCollections);
|
||||
|
@ -2164,7 +2179,7 @@ nsCycleCollector::Collect(PRUint32 aTryCollections)
|
|||
}
|
||||
|
||||
mFollowupCollection = PR_FALSE;
|
||||
|
||||
mCollectedObjects = 0;
|
||||
nsAutoTPtrArray<PtrInfo, 4000> whiteNodes;
|
||||
mWhiteNodes = &whiteNodes;
|
||||
|
||||
|
@ -2224,7 +2239,7 @@ nsCycleCollector::Collect(PRUint32 aTryCollections)
|
|||
#ifdef DEBUG_CC
|
||||
ExplainLiveExpectedGarbage();
|
||||
#endif
|
||||
return totalCollections > 0;
|
||||
return mCollectedObjects;
|
||||
}
|
||||
|
||||
PRBool
|
||||
|
@ -2340,7 +2355,7 @@ nsCycleCollector::BeginCollection()
|
|||
RootWhite();
|
||||
|
||||
#ifdef COLLECT_TIME_DEBUG
|
||||
printf("cc: CollectWhite() took %lldms\n",
|
||||
printf("cc: RootWhite() took %lldms\n",
|
||||
(PR_Now() - now) / PR_USEC_PER_MSEC);
|
||||
#endif
|
||||
}
|
||||
|
@ -2354,8 +2369,16 @@ nsCycleCollector::BeginCollection()
|
|||
PRBool
|
||||
nsCycleCollector::FinishCollection()
|
||||
{
|
||||
#ifdef COLLECT_TIME_DEBUG
|
||||
PRTime now = PR_Now();
|
||||
#endif
|
||||
PRBool collected = CollectWhite();
|
||||
|
||||
#ifdef COLLECT_TIME_DEBUG
|
||||
printf("cc: CollectWhite() took %lldms\n",
|
||||
(PR_Now() - now) / PR_USEC_PER_MSEC);
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_CC
|
||||
mStats.mCollection++;
|
||||
if (mParams.mReportStats)
|
||||
|
@ -2372,6 +2395,12 @@ nsCycleCollector::FinishCollection()
|
|||
return collected;
|
||||
}
|
||||
|
||||
PRUint32
|
||||
nsCycleCollector::SuspectedCount()
|
||||
{
|
||||
return mPurpleBuf.Count();
|
||||
}
|
||||
|
||||
void
|
||||
nsCycleCollector::Shutdown()
|
||||
{
|
||||
|
@ -2780,10 +2809,16 @@ NS_CycleCollectorForget(nsISupports *n)
|
|||
}
|
||||
|
||||
|
||||
PRBool
|
||||
PRUint32
|
||||
nsCycleCollector_collect()
|
||||
{
|
||||
return sCollector ? sCollector->Collect() : PR_FALSE;
|
||||
return sCollector ? sCollector->Collect() : 0;
|
||||
}
|
||||
|
||||
PRUint32
|
||||
nsCycleCollector_suspectedCount()
|
||||
{
|
||||
return sCollector ? sCollector->SuspectedCount() : 0;
|
||||
}
|
||||
|
||||
PRBool
|
||||
|
|
|
@ -60,8 +60,9 @@ struct nsCycleCollectionLanguageRuntime
|
|||
};
|
||||
|
||||
nsresult nsCycleCollector_startup();
|
||||
// Returns PR_TRUE if some nodes were collected.
|
||||
NS_COM PRBool nsCycleCollector_collect();
|
||||
// Returns the number of collected nodes.
|
||||
NS_COM PRUint32 nsCycleCollector_collect();
|
||||
NS_COM PRUint32 nsCycleCollector_suspectedCount();
|
||||
void nsCycleCollector_shutdown();
|
||||
|
||||
// The JS runtime is special, it needs to call cycle collection during its GC.
|
||||
|
|
Загрузка…
Ссылка в новой задаче