Bug 963844 - Scale ICC budget by time between slices. r=smaug

If we exceed the desired length of time between ICC slices, proportionally scale up the slice budget to try to ensure a constant amount of collection work is done per unit of time, even when the browser is under heavy load.

As part of this, track the time the last slice from the current ICC ended.
This commit is contained in:
Andrew McCreight 2014-03-06 10:54:37 -08:00
parent f0bd81877d
commit 803f610f27

View File

@ -1985,6 +1985,7 @@ struct CycleCollectorStats
void Clear()
{
mBeginSliceTime = TimeStamp();
mEndSliceTime = TimeStamp();
mBeginTime = TimeStamp();
mMaxGCDuration = 0;
mRanSyncForgetSkippable = false;
@ -2005,7 +2006,8 @@ struct CycleCollectorStats
return;
}
uint32_t sliceTime = TimeUntilNow(mBeginSliceTime);
mEndSliceTime = TimeStamp::Now();
uint32_t sliceTime = TimeBetween(mBeginSliceTime, mEndSliceTime);
mMaxSliceTime = std::max(mMaxSliceTime, sliceTime);
mTotalSliceTime += sliceTime;
mBeginSliceTime = TimeStamp();
@ -2017,6 +2019,9 @@ struct CycleCollectorStats
// Time the current slice began, including any GC finishing.
TimeStamp mBeginSliceTime;
// Time the previous slice of the current CC ended.
TimeStamp mEndSliceTime;
// Time the current cycle collection began.
TimeStamp mBeginTime;
@ -2047,22 +2052,6 @@ 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 (TimeUntilNow(gCCStats.mBeginTime) >= kMaxICCDuration) {
return -1;
}
return kICCSliceBudget;
}
void
CycleCollectorStats::PrepareForCycleCollectionSlice(int32_t aExtraForgetSkippableCalls)
{
@ -2132,10 +2121,29 @@ nsJSContext::RunCycleCollectorSlice()
PROFILER_LABEL("CC", "RunCycleCollectorSlice");
// Ideally, the slice time would be decreased by the amount of
// time spent on PrepareForCycleCollection().
gCCStats.PrepareForCycleCollectionSlice();
nsCycleCollector_collectSlice(ICCSliceTime());
// Decide how long we want to budget for this slice. By default,
// use an unlimited budget.
int64_t sliceBudget = -1;
if (sIncrementalCC) {
if (gCCStats.mBeginTime.IsNull()) {
// If no CC is in progress, use the standard slice time.
sliceBudget = kICCSliceBudget;
} else {
TimeStamp now = TimeStamp::Now();
// Only run a limited slice if we're within the max running time.
if (TimeBetween(gCCStats.mBeginTime, now) < kMaxICCDuration) {
float sliceMultiplier = std::max(TimeBetween(gCCStats.mEndSliceTime, now) / (float)kICCIntersliceDelay, 1.0f);
sliceBudget = kICCSliceBudget * sliceMultiplier;
}
}
}
nsCycleCollector_collectSlice(sliceBudget);
gCCStats.FinishCycleCollectionSlice();
}