зеркало из https://github.com/mozilla/gecko-dev.git
Bug 937960, part 3 - Pass in a small time budget with ICC. r=smaug
This commit is contained in:
Родитель
987c5c3e05
Коммит
53e4433905
|
@ -124,6 +124,12 @@ static PRLogModuleInfo* gJSDiagnostics;
|
|||
// Maximum amount of time that should elapse between incremental CC slices
|
||||
static const int64_t kICCIntersliceDelay = 32; // ms
|
||||
|
||||
// Time budget for an incremental CC slice
|
||||
static const int64_t kICCSliceBudget = 10; // ms
|
||||
|
||||
// Maximum total duration for an ICC
|
||||
static const uint32_t kMaxICCDuration = 2000; // ms
|
||||
|
||||
// Force a CC after this long if there's more than NS_CC_FORCED_PURPLE_LIMIT
|
||||
// objects in the purple buffer.
|
||||
#define NS_CC_FORCED (2 * 60 * PR_USEC_PER_SEC) // 2 min
|
||||
|
@ -2019,6 +2025,22 @@ struct CycleCollectorStats
|
|||
|
||||
CycleCollectorStats gCCStats;
|
||||
|
||||
static int64_t
|
||||
ICCSliceTime()
|
||||
{
|
||||
// If CC is not incremental, use an unlimited budget.
|
||||
if (!sIncrementalCC) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// If an ICC is in progress and is taking too long, finish it off.
|
||||
if (gCCStats.mBeginTime != 0 &&
|
||||
TimeBetween(gCCStats.mBeginTime, PR_Now()) >= kMaxICCDuration) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return kICCSliceBudget;
|
||||
}
|
||||
|
||||
static void
|
||||
PrepareForCycleCollection(int32_t aExtraForgetSkippableCalls = 0)
|
||||
|
@ -2076,15 +2098,18 @@ nsJSContext::CycleCollectNow(nsICycleCollectorListener *aListener,
|
|||
|
||||
//static
|
||||
void
|
||||
nsJSContext::ScheduledCycleCollectNow()
|
||||
nsJSContext::ScheduledCycleCollectNow(int64_t aSliceTime)
|
||||
{
|
||||
if (!NS_IsMainThread()) {
|
||||
return;
|
||||
}
|
||||
|
||||
PROFILER_LABEL("CC", "ScheduledCycleCollectNow");
|
||||
|
||||
// Ideally, the slice time would be decreased by the amount of
|
||||
// time spent on PrepareForCycleCollection().
|
||||
PrepareForCycleCollection();
|
||||
nsCycleCollector_scheduledCollect();
|
||||
nsCycleCollector_scheduledCollect(aSliceTime);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -2108,7 +2133,7 @@ ICCTimerFired(nsITimer* aTimer, void* aClosure)
|
|||
}
|
||||
}
|
||||
|
||||
nsJSContext::ScheduledCycleCollectNow();
|
||||
nsJSContext::ScheduledCycleCollectNow(ICCSliceTime());
|
||||
}
|
||||
|
||||
//static
|
||||
|
@ -2359,7 +2384,7 @@ CCTimerFired(nsITimer *aTimer, void *aClosure)
|
|||
// We are in the final timer fire and still meet the conditions for
|
||||
// triggering a CC. Let CycleCollectNow finish the current IGC, if any,
|
||||
// because that will allow us to include the GC time in the CC pause.
|
||||
nsJSContext::ScheduledCycleCollectNow();
|
||||
nsJSContext::ScheduledCycleCollectNow(ICCSliceTime());
|
||||
}
|
||||
} else if ((sPreviousSuspectedCount + 100) <= suspected) {
|
||||
// Only do a forget skippable if there are more than a few new objects.
|
||||
|
|
|
@ -101,11 +101,17 @@ public:
|
|||
IsShrinking aShrinking = NonShrinkingGC,
|
||||
int64_t aSliceMillis = 0);
|
||||
static void ShrinkGCBuffersNow();
|
||||
|
||||
// If aExtraForgetSkippableCalls is -1, forgetSkippable won't be
|
||||
// called even if the previous collection was GC.
|
||||
static void CycleCollectNow(nsICycleCollectorListener *aListener = nullptr,
|
||||
int32_t aExtraForgetSkippableCalls = 0);
|
||||
static void ScheduledCycleCollectNow();
|
||||
|
||||
// If aSliceTime is negative, the CC will run to completion. If aSliceTime
|
||||
// is 0, only a minimum quantum of work will be done. Otherwise, aSliceTime
|
||||
// will be used as the time budget for the slice, in ms.
|
||||
static void ScheduledCycleCollectNow(int64_t aSliceTime);
|
||||
|
||||
static void BeginCycleCollectionCallback();
|
||||
static void EndCycleCollectionCallback(mozilla::CycleCollectorResults &aResults);
|
||||
|
||||
|
|
|
@ -3056,7 +3056,8 @@ nsCycleCollector::Collect(ccType aCCType,
|
|||
// don't want to abandon the current CC, because the graph contains
|
||||
// information about purple roots. So we synchronously finish off
|
||||
// the current CC.
|
||||
void nsCycleCollector::PrepareForGarbageCollection()
|
||||
void
|
||||
nsCycleCollector::PrepareForGarbageCollection()
|
||||
{
|
||||
if (mIncrementalPhase == IdlePhase) {
|
||||
MOZ_ASSERT(mGraph.IsEmpty(), "Non-empty graph when idle");
|
||||
|
@ -3551,7 +3552,7 @@ nsCycleCollector_collect(nsICycleCollectorListener *aManualListener)
|
|||
}
|
||||
|
||||
void
|
||||
nsCycleCollector_scheduledCollect()
|
||||
nsCycleCollector_scheduledCollect(int64_t aSliceTime)
|
||||
{
|
||||
CollectorData *data = sCollectorData.get();
|
||||
|
||||
|
@ -3560,8 +3561,13 @@ nsCycleCollector_scheduledCollect()
|
|||
MOZ_ASSERT(data->mCollector);
|
||||
|
||||
PROFILER_LABEL("CC", "nsCycleCollector_scheduledCollect");
|
||||
SliceBudget unlimitedBudget;
|
||||
data->mCollector->Collect(ScheduledCC, unlimitedBudget, nullptr);
|
||||
SliceBudget budget;
|
||||
if (aSliceTime > 0) {
|
||||
budget = SliceBudget::TimeBudget(aSliceTime);
|
||||
} else if (aSliceTime == 0) {
|
||||
budget = SliceBudget::WorkBudget(1);
|
||||
}
|
||||
data->mCollector->Collect(ScheduledCC, budget, nullptr);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -41,7 +41,11 @@ void nsCycleCollector_dispatchDeferredDeletion(bool aContinuation = false);
|
|||
bool nsCycleCollector_doDeferredDeletion();
|
||||
|
||||
void nsCycleCollector_collect(nsICycleCollectorListener *aManualListener);
|
||||
void nsCycleCollector_scheduledCollect();
|
||||
|
||||
// If aSliceTime is negative, the CC will run to completion. If aSliceTime
|
||||
// is 0, only a minimum quantum of work will be done. Otherwise, aSliceTime
|
||||
// will be used as the time budget for the slice, in ms.
|
||||
void nsCycleCollector_scheduledCollect(int64_t aSliceTime);
|
||||
|
||||
uint32_t nsCycleCollector_suspectedCount();
|
||||
void nsCycleCollector_shutdown();
|
||||
|
|
Загрузка…
Ссылка в новой задаче