mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 21:31:04 +00:00
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:
parent
2af2d39a1c
commit
a559ffee38
@ -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,7 @@ 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.
|
||||
@ -380,7 +383,8 @@ js::SliceBudget CCGCScheduler::ComputeCCSliceBudget(
|
||||
// baseBudget will be negative and we will end up returning
|
||||
// laterSliceBudget.
|
||||
return js::SliceBudget(
|
||||
std::max({delaySliceBudget, laterSliceBudget, baseBudget}));
|
||||
js::TimeBudget(std::max({delaySliceBudget, laterSliceBudget, baseBudget})),
|
||||
kNumCCNodesBetweenTimeChecks);
|
||||
}
|
||||
|
||||
inline TimeDuration CCGCScheduler::ComputeInterSliceGCBudget(
|
||||
|
@ -22,6 +22,7 @@ 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 +44,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 +56,11 @@ 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 +68,20 @@ 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() {
|
||||
counter = 0;
|
||||
}
|
||||
|
||||
bool isOverBudget() { return counter <= 0 && checkOverBudget(); }
|
||||
|
||||
bool isWorkBudget() const { return budget.is<WorkBudget>(); }
|
||||
|
@ -3175,8 +3175,8 @@ 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 +3206,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);
|
||||
|
Loading…
Reference in New Issue
Block a user