Bug 1703374 - Provide SliceBudget users with more control of when and how often time checks happen r=jonco

Differential Revision: https://phabricator.services.mozilla.com/D111008
This commit is contained in:
Steve Fink 2021-04-28 16:37:32 +00:00
Родитель 510fc82a68
Коммит 600f475b8f
4 изменённых файлов: 33 добавлений и 16 удалений

Просмотреть файл

@ -58,6 +58,9 @@ static const TimeDuration kMaxCCLockedoutTime = TimeDuration::FromSeconds(30);
// Trigger a CC if the purple buffer exceeds this size when we check it.
static const uint32_t kCCPurpleLimit = 200;
// How many cycle collected nodes to traverse between time checks.
static const int64_t kNumCCNodesBetweenTimeChecks = 1000;
enum class CCRunnerAction {
None,
ForgetSkippable,
@ -351,7 +354,8 @@ js::SliceBudget CCGCScheduler::ComputeCCSliceBudget(
if (aCCBeginTime.IsNull()) {
// If no CC is in progress, use the standard slice time.
return js::SliceBudget(baseBudget);
return js::SliceBudget(js::TimeBudget(baseBudget),
kNumCCNodesBetweenTimeChecks);
}
// Only run a limited slice if we're within the max running time.
@ -379,8 +383,9 @@ js::SliceBudget CCGCScheduler::ComputeCCSliceBudget(
// Note: We may have already overshot the deadline, in which case
// baseBudget will be negative and we will end up returning
// laterSliceBudget.
return js::SliceBudget(
std::max({delaySliceBudget, laterSliceBudget, baseBudget}));
return js::SliceBudget(js::TimeBudget(std::max(
{delaySliceBudget, laterSliceBudget, baseBudget})),
kNumCCNodesBetweenTimeChecks);
}
inline TimeDuration CCGCScheduler::ComputeInterSliceGCBudget(

Просмотреть файл

@ -22,6 +22,8 @@ struct JS_PUBLIC_API TimeBudget {
mozilla::TimeStamp deadline; // Calculated when SliceBudget is constructed.
explicit TimeBudget(int64_t milliseconds) : budget(milliseconds) {}
explicit TimeBudget(mozilla::TimeDuration duration)
: TimeBudget(duration.ToMilliseconds()) {}
};
struct JS_PUBLIC_API WorkBudget {
@ -43,8 +45,11 @@ struct UnlimitedBudget {};
*/
class JS_PUBLIC_API SliceBudget {
static const intptr_t UnlimitedCounter = INTPTR_MAX;
static const intptr_t DefaultStepsPerTimeCheck = 1000;
mozilla::Variant<TimeBudget, WorkBudget, UnlimitedBudget> budget;
int64_t stepsPerTimeCheck = DefaultStepsPerTimeCheck;
int64_t counter;
SliceBudget() : budget(UnlimitedBudget()), counter(UnlimitedCounter) {}
@ -52,13 +57,12 @@ class JS_PUBLIC_API SliceBudget {
bool checkOverBudget();
public:
static const intptr_t StepsPerTimeCheck = 1000;
// Use to create an unlimited budget.
static SliceBudget unlimited() { return SliceBudget(); }
// Instantiate as SliceBudget(TimeBudget(n)).
explicit SliceBudget(TimeBudget time);
explicit SliceBudget(TimeBudget time,
int64_t stepsPerTimeCheck = DefaultStepsPerTimeCheck);
// Instantiate as SliceBudget(WorkBudget(n)).
explicit SliceBudget(WorkBudget work);
@ -66,11 +70,22 @@ class JS_PUBLIC_API SliceBudget {
explicit SliceBudget(mozilla::TimeDuration time)
: SliceBudget(TimeBudget(time.ToMilliseconds())) {}
// Register having performed the given number of steps (counted against a
// work budget, or progress towards the next time or callback check).
void step(uint64_t steps = 1) {
MOZ_ASSERT(steps > 0);
counter -= steps;
}
// Do enough steps to force an "expensive" (time and/or callback) check on
// the next call to isOverBudget. Useful when switching between major phases
// of an operation like a cycle collection.
void stepAndForceCheck() {
if (!isUnlimited()) {
counter = 0;
}
}
bool isOverBudget() { return counter <= 0 && checkOverBudget(); }
bool isWorkBudget() const { return budget.is<WorkBudget>(); }

Просмотреть файл

@ -3175,8 +3175,10 @@ void ArenaLists::checkNoArenasToUpdateForKind(AllocKind kind) {
#endif
}
SliceBudget::SliceBudget(TimeBudget time)
: budget(time), counter(StepsPerTimeCheck) {
SliceBudget::SliceBudget(TimeBudget time, int64_t stepsPerTimeCheckArg)
: budget(TimeBudget(time)),
stepsPerTimeCheck(stepsPerTimeCheckArg),
counter(stepsPerTimeCheckArg) {
budget.as<TimeBudget>().deadline =
ReallyNow() + TimeDuration::FromMilliseconds(timeBudget());
}
@ -3206,7 +3208,7 @@ bool SliceBudget::checkOverBudget() {
return true;
}
counter = StepsPerTimeCheck;
counter = stepsPerTimeCheck;
return false;
}

Просмотреть файл

@ -2038,10 +2038,6 @@ void CCGraphBuilder::DoneAddingRoots() {
}
MOZ_NEVER_INLINE bool CCGraphBuilder::BuildGraph(SliceBudget& aBudget) {
const intptr_t kNumNodesBetweenTimeChecks = 1000;
const intptr_t kStep =
SliceBudget::StepsPerTimeCheck / kNumNodesBetweenTimeChecks;
MOZ_ASSERT(mCurrNode);
while (!aBudget.isOverBudget() && !mCurrNode->IsDone()) {
@ -2068,7 +2064,7 @@ MOZ_NEVER_INLINE bool CCGraphBuilder::BuildGraph(SliceBudget& aBudget) {
SetLastChild();
}
aBudget.step(kStep * (mNoteChildCount + 1));
aBudget.step(mNoteChildCount + 1);
}
if (!mCurrNode->IsDone()) {
@ -3446,8 +3442,7 @@ bool nsCycleCollector::Collect(ccType aCCType, SliceBudget& aBudget,
break;
}
if (continueSlice) {
// Force SliceBudget::isOverBudget to check the time.
aBudget.step(SliceBudget::StepsPerTimeCheck);
aBudget.stepAndForceCheck();
continueSlice = !aBudget.isOverBudget();
}
} while (continueSlice);