зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1580883 - Use TimeDuration for constants in nsJSEnvironment.cpp r=mccr8
Differential Revision: https://phabricator.services.mozilla.com/D45695 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
559e2c332d
Коммит
99e7fae124
|
@ -106,34 +106,40 @@ const size_t gStackSize = 8192;
|
|||
|
||||
// The amount of time we wait between a request to CC (after GC ran)
|
||||
// and doing the actual CC.
|
||||
static const uint32_t kCCDelay = 6000; // ms
|
||||
static const TimeDuration kCCDelay = TimeDuration::FromSeconds(6);
|
||||
|
||||
static const int32_t kCCSkippableDelay = 250; // ms
|
||||
static const TimeDuration kCCSkippableDelay =
|
||||
TimeDuration::FromMilliseconds(250);
|
||||
|
||||
// In case the cycle collector isn't run at all, we don't want
|
||||
// forget skippables to run too often. So limit the forget skippable cycle to
|
||||
// start at earliest 2000 ms after the end of the previous cycle.
|
||||
static const uint32_t kTimeBetweenForgetSkippableCycles = 2000; // ms
|
||||
// In case the cycle collector isn't run at all, we don't want forget skippables
|
||||
// to run too often. So limit the forget skippable cycle to start at earliest 2
|
||||
// seconds after the end of the previous cycle.
|
||||
static const TimeDuration kTimeBetweenForgetSkippableCycles =
|
||||
TimeDuration::FromSeconds(2);
|
||||
|
||||
// ForgetSkippable is usually fast, so we can use small budgets.
|
||||
// This isn't a real budget but a hint to IdleTaskRunner whether there
|
||||
// is enough time to call ForgetSkippable.
|
||||
static const int64_t kForgetSkippableSliceDuration = 2;
|
||||
static const TimeDuration kForgetSkippableSliceDuration =
|
||||
TimeDuration::FromMilliseconds(2);
|
||||
|
||||
// Maximum amount of time that should elapse between incremental CC slices
|
||||
static const int64_t kICCIntersliceDelay = 64; // ms
|
||||
static const TimeDuration kICCIntersliceDelay =
|
||||
TimeDuration::FromMilliseconds(64);
|
||||
|
||||
// Time budget for an incremental CC slice when using timer to run it.
|
||||
static const int64_t kICCSliceBudget = 3; // ms
|
||||
static const TimeDuration kICCSliceBudget = TimeDuration::FromMilliseconds(3);
|
||||
// Minimum budget for an incremental CC slice when using idle time to run it.
|
||||
static const int64_t kIdleICCSliceBudget = 2; // ms
|
||||
static const TimeDuration kIdleICCSliceBudget =
|
||||
TimeDuration::FromMilliseconds(2);
|
||||
|
||||
// Maximum total duration for an ICC
|
||||
static const uint32_t kMaxICCDuration = 2000; // ms
|
||||
static const TimeDuration kMaxICCDuration = TimeDuration::FromSeconds(2);
|
||||
|
||||
// Force a CC after this long if there's more than NS_CC_FORCED_PURPLE_LIMIT
|
||||
// objects in the purple buffer.
|
||||
static const uint32_t kCCForced = (2 * 60 * PR_USEC_PER_SEC); // 2 min
|
||||
static const TimeDuration kCCForced =
|
||||
TimeDuration::FromSeconds(2 * 60); // 2 min
|
||||
static const uint32_t kCCForcedPurpleLimit = 10;
|
||||
|
||||
// Don't allow an incremental GC to lock out the CC for too long.
|
||||
|
@ -1138,6 +1144,10 @@ static void FinishAnyIncrementalGC() {
|
|||
}
|
||||
}
|
||||
|
||||
static inline js::SliceBudget BudgetFromDuration(TimeDuration duration) {
|
||||
return js::SliceBudget(js::TimeBudget(duration.ToMilliseconds()));
|
||||
}
|
||||
|
||||
static void FireForgetSkippable(uint32_t aSuspected, bool aRemoveChildless,
|
||||
TimeStamp aDeadline) {
|
||||
AUTO_PROFILER_TRACING(
|
||||
|
@ -1177,11 +1187,10 @@ static void FireForgetSkippable(uint32_t aSuspected, bool aRemoveChildless,
|
|||
FinishAnyIncrementalGC();
|
||||
bool earlyForgetSkippable = sCleanupsSinceLastGC < kMajorForgetSkippableCalls;
|
||||
|
||||
int64_t budgetMs =
|
||||
aDeadline.IsNull()
|
||||
? kForgetSkippableSliceDuration
|
||||
: int64_t((aDeadline - TimeStamp::Now()).ToMilliseconds());
|
||||
js::SliceBudget budget = js::SliceBudget(js::TimeBudget(budgetMs));
|
||||
TimeDuration budgetTime = aDeadline ? (aDeadline - TimeStamp::Now())
|
||||
: kForgetSkippableSliceDuration;
|
||||
|
||||
js::SliceBudget budget = BudgetFromDuration(budgetTime);
|
||||
nsCycleCollector_forgetSkippable(budget, aRemoveChildless,
|
||||
earlyForgetSkippable);
|
||||
|
||||
|
@ -1223,18 +1232,28 @@ static void FireForgetSkippable(uint32_t aSuspected, bool aRemoveChildless,
|
|||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE
|
||||
static uint32_t TimeBetween(TimeStamp start, TimeStamp end) {
|
||||
static TimeDuration TimeBetween(TimeStamp start, TimeStamp end) {
|
||||
MOZ_ASSERT(end >= start);
|
||||
return (uint32_t)((end - start).ToMilliseconds());
|
||||
return end - start;
|
||||
}
|
||||
|
||||
static uint32_t TimeUntilNow(TimeStamp start) {
|
||||
MOZ_ALWAYS_INLINE
|
||||
static uint32_t TimeBetweenInMillis(TimeStamp start, TimeStamp end) {
|
||||
return uint32_t(TimeBetween(start, end).ToMilliseconds());
|
||||
}
|
||||
|
||||
static TimeDuration TimeUntilNow(TimeStamp start) {
|
||||
if (start.IsNull()) {
|
||||
return 0;
|
||||
return TimeDuration();
|
||||
}
|
||||
return TimeBetween(start, TimeStamp::Now());
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE
|
||||
static uint32_t TimeUntilNowInMillis(TimeStamp start) {
|
||||
return uint32_t(TimeUntilNow(start).ToMilliseconds());
|
||||
}
|
||||
|
||||
struct CycleCollectorStats {
|
||||
constexpr CycleCollectorStats()
|
||||
: mMaxGCDuration(0),
|
||||
|
@ -1315,7 +1334,7 @@ struct CycleCollectorStats {
|
|||
percent);
|
||||
}
|
||||
|
||||
uint32_t sliceTime = TimeBetween(mBeginSliceTime, mEndSliceTime);
|
||||
uint32_t sliceTime = TimeBetweenInMillis(mBeginSliceTime, mEndSliceTime);
|
||||
mMaxSliceTime = std::max(mMaxSliceTime, sliceTime);
|
||||
mMaxSliceTimeSinceClear = std::max(mMaxSliceTimeSinceClear, sliceTime);
|
||||
mTotalSliceTime += sliceTime;
|
||||
|
@ -1376,7 +1395,7 @@ void CycleCollectorStats::PrepareForCycleCollectionSlice(TimeStamp aDeadline) {
|
|||
if (sCCLockedOut) {
|
||||
mAnyLockedOut = true;
|
||||
FinishAnyIncrementalGC();
|
||||
uint32_t gcTime = TimeBetween(mBeginSliceTime, TimeStamp::Now());
|
||||
uint32_t gcTime = TimeBetweenInMillis(mBeginSliceTime, TimeStamp::Now());
|
||||
mMaxGCDuration = std::max(mMaxGCDuration, gcTime);
|
||||
}
|
||||
}
|
||||
|
@ -1392,8 +1411,8 @@ void CycleCollectorStats::RunForgetSkippable() {
|
|||
}
|
||||
|
||||
if (ranSyncForgetSkippable) {
|
||||
mMaxSkippableDuration =
|
||||
std::max(mMaxSkippableDuration, TimeUntilNow(beginForgetSkippable));
|
||||
mMaxSkippableDuration = std::max(
|
||||
mMaxSkippableDuration, TimeUntilNowInMillis(beginForgetSkippable));
|
||||
mRanSyncForgetSkippable = true;
|
||||
}
|
||||
}
|
||||
|
@ -1429,44 +1448,44 @@ void nsJSContext::RunCycleCollectorSlice(TimeStamp aDeadline) {
|
|||
js::SliceBudget budget = js::SliceBudget::unlimited();
|
||||
|
||||
if (sIncrementalCC) {
|
||||
int64_t baseBudget = kICCSliceBudget;
|
||||
TimeDuration baseBudget = kICCSliceBudget;
|
||||
if (!aDeadline.IsNull()) {
|
||||
baseBudget = int64_t((aDeadline - TimeStamp::Now()).ToMilliseconds());
|
||||
baseBudget = aDeadline - TimeStamp::Now();
|
||||
}
|
||||
|
||||
if (gCCStats.mBeginTime.IsNull()) {
|
||||
// If no CC is in progress, use the standard slice time.
|
||||
budget = js::SliceBudget(js::TimeBudget(baseBudget));
|
||||
budget = BudgetFromDuration(baseBudget);
|
||||
} else {
|
||||
TimeStamp now = TimeStamp::Now();
|
||||
|
||||
// Only run a limited slice if we're within the max running time.
|
||||
uint32_t runningTime = TimeBetween(gCCStats.mBeginTime, now);
|
||||
TimeDuration runningTime = TimeBetween(gCCStats.mBeginTime, now);
|
||||
if (runningTime < kMaxICCDuration) {
|
||||
const float maxSlice = MainThreadIdlePeriod::GetLongIdlePeriod();
|
||||
const TimeDuration maxSlice = TimeDuration::FromMilliseconds(
|
||||
MainThreadIdlePeriod::GetLongIdlePeriod());
|
||||
|
||||
// Try to make up for a delay in running this slice.
|
||||
float sliceDelayMultiplier = TimeBetween(gCCStats.mEndSliceTime, now) /
|
||||
(float)kICCIntersliceDelay;
|
||||
float delaySliceBudget =
|
||||
std::min(baseBudget * sliceDelayMultiplier, maxSlice);
|
||||
double sliceDelayMultiplier =
|
||||
TimeBetween(gCCStats.mEndSliceTime, now) / kICCIntersliceDelay;
|
||||
TimeDuration delaySliceBudget =
|
||||
std::min(baseBudget.MultDouble(sliceDelayMultiplier), maxSlice);
|
||||
|
||||
// Increase slice budgets up to |maxSlice| as we approach
|
||||
// half way through the ICC, to avoid large sync CCs.
|
||||
float percentToHalfDone =
|
||||
std::min(2.0f * runningTime / kMaxICCDuration, 1.0f);
|
||||
float laterSliceBudget = maxSlice * percentToHalfDone;
|
||||
double percentToHalfDone =
|
||||
std::min(2.0 * (runningTime / kMaxICCDuration), 1.0);
|
||||
TimeDuration laterSliceBudget = maxSlice.MultDouble(percentToHalfDone);
|
||||
|
||||
budget = js::SliceBudget(js::TimeBudget(
|
||||
std::max({delaySliceBudget, laterSliceBudget, (float)baseBudget})));
|
||||
budget = BudgetFromDuration(
|
||||
std::max({delaySliceBudget, laterSliceBudget, baseBudget}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsCycleCollector_collectSlice(
|
||||
budget,
|
||||
aDeadline.IsNull() ||
|
||||
(aDeadline - TimeStamp::Now()).ToMilliseconds() < kICCSliceBudget);
|
||||
aDeadline.IsNull() || (aDeadline - TimeStamp::Now()) < kICCSliceBudget);
|
||||
|
||||
gCCStats.FinishCycleCollectionSlice();
|
||||
}
|
||||
|
@ -1543,8 +1562,9 @@ void nsJSContext::BeginCycleCollectionCallback() {
|
|||
// finish it.
|
||||
sICCRunner = IdleTaskRunner::Create(
|
||||
ICCRunnerFired, "BeginCycleCollectionCallback::ICCRunnerFired",
|
||||
kICCIntersliceDelay, kIdleICCSliceBudget, true,
|
||||
[] { return sShuttingDown; }, TaskCategory::GarbageCollection);
|
||||
kICCIntersliceDelay.ToMilliseconds(),
|
||||
kIdleICCSliceBudget.ToMilliseconds(), true, [] { return sShuttingDown; },
|
||||
TaskCategory::GarbageCollection);
|
||||
}
|
||||
|
||||
// static
|
||||
|
@ -1562,15 +1582,16 @@ void nsJSContext::EndCycleCollectionCallback(CycleCollectorResults& aResults) {
|
|||
sCCollectedZonesWaitingForGC += aResults.mFreedJSZones;
|
||||
|
||||
TimeStamp endCCTimeStamp = TimeStamp::Now();
|
||||
uint32_t ccNowDuration = TimeBetween(gCCStats.mBeginTime, endCCTimeStamp);
|
||||
TimeDuration ccNowDuration = TimeBetween(gCCStats.mBeginTime, endCCTimeStamp);
|
||||
|
||||
if (NeedsGCAfterCC()) {
|
||||
MOZ_ASSERT(StaticPrefs::javascript_options_gc_delay() > kMaxICCDuration,
|
||||
MOZ_ASSERT(StaticPrefs::javascript_options_gc_delay() >
|
||||
kMaxICCDuration.ToMilliseconds(),
|
||||
"A max duration ICC shouldn't reduce GC delay to 0");
|
||||
|
||||
PokeGC(JS::GCReason::CC_WAITING, nullptr,
|
||||
StaticPrefs::javascript_options_gc_delay() -
|
||||
std::min(ccNowDuration, kMaxICCDuration));
|
||||
std::min(ccNowDuration, kMaxICCDuration).ToMilliseconds());
|
||||
}
|
||||
|
||||
// Log information about the CC via telemetry, JSON and the console.
|
||||
|
@ -1578,15 +1599,15 @@ void nsJSContext::EndCycleCollectionCallback(CycleCollectorResults& aResults) {
|
|||
gCCStats.mAnyLockedOut);
|
||||
Telemetry::Accumulate(Telemetry::CYCLE_COLLECTOR_SYNC_SKIPPABLE,
|
||||
gCCStats.mRanSyncForgetSkippable);
|
||||
Telemetry::Accumulate(Telemetry::CYCLE_COLLECTOR_FULL, ccNowDuration);
|
||||
Telemetry::Accumulate(Telemetry::CYCLE_COLLECTOR_FULL,
|
||||
ccNowDuration.ToMilliseconds());
|
||||
Telemetry::Accumulate(Telemetry::CYCLE_COLLECTOR_MAX_PAUSE,
|
||||
gCCStats.mMaxSliceTime);
|
||||
|
||||
if (!sLastCCEndTime.IsNull()) {
|
||||
// TimeBetween returns milliseconds, but we want to report seconds.
|
||||
uint32_t timeBetween =
|
||||
TimeBetween(sLastCCEndTime, gCCStats.mBeginTime) / 1000;
|
||||
Telemetry::Accumulate(Telemetry::CYCLE_COLLECTOR_TIME_BETWEEN, timeBetween);
|
||||
TimeDuration timeBetween = TimeBetween(sLastCCEndTime, gCCStats.mBeginTime);
|
||||
Telemetry::Accumulate(Telemetry::CYCLE_COLLECTOR_TIME_BETWEEN,
|
||||
timeBetween.ToSeconds());
|
||||
}
|
||||
sLastCCEndTime = endCCTimeStamp;
|
||||
|
||||
|
@ -1643,7 +1664,7 @@ void nsJSContext::EndCycleCollectionCallback(CycleCollectorResults& aResults) {
|
|||
if (StaticPrefs::javascript_options_mem_notify()) {
|
||||
const char16_t* kJSONFmt =
|
||||
u"{ \"timestamp\": %llu, "
|
||||
u"\"duration\": %lu, "
|
||||
u"\"duration\": %.f, "
|
||||
u"\"max_slice_pause\": %lu, "
|
||||
u"\"total_slice_pause\": %lu, "
|
||||
u"\"max_finish_gc_duration\": %lu, "
|
||||
|
@ -1670,10 +1691,10 @@ void nsJSContext::EndCycleCollectionCallback(CycleCollectorResults& aResults) {
|
|||
|
||||
nsString json;
|
||||
nsTextFormatter::ssprintf(
|
||||
json, kJSONFmt, PR_Now(), ccNowDuration, gCCStats.mMaxSliceTime,
|
||||
gCCStats.mTotalSliceTime, gCCStats.mMaxGCDuration,
|
||||
gCCStats.mMaxSkippableDuration, gCCStats.mSuspected,
|
||||
aResults.mVisitedRefCounted, aResults.mVisitedGCed,
|
||||
json, kJSONFmt, PR_Now(), ccNowDuration.ToMilliseconds(),
|
||||
gCCStats.mMaxSliceTime, gCCStats.mTotalSliceTime,
|
||||
gCCStats.mMaxGCDuration, gCCStats.mMaxSkippableDuration,
|
||||
gCCStats.mSuspected, aResults.mVisitedRefCounted, aResults.mVisitedGCed,
|
||||
aResults.mFreedRefCounted, aResults.mFreedGCed, sCCollectedWaitingForGC,
|
||||
sCCollectedZonesWaitingForGC, sLikelyShortLivingObjectsNeedingGC,
|
||||
aResults.mForcedGC, sForgetSkippableBeforeCC,
|
||||
|
@ -1798,9 +1819,9 @@ static bool CCRunnerFired(TimeStamp aDeadline) {
|
|||
return false;
|
||||
}
|
||||
|
||||
static uint32_t ccDelay = kCCDelay;
|
||||
static TimeDuration ccDelay = kCCDelay;
|
||||
if (sCCLockedOut) {
|
||||
ccDelay = kCCDelay / 3;
|
||||
ccDelay = kCCDelay / int64_t(3);
|
||||
|
||||
TimeStamp now = TimeStamp::Now();
|
||||
if (!sCCLockedOutTime) {
|
||||
|
@ -1827,7 +1848,7 @@ static bool CCRunnerFired(TimeStamp aDeadline) {
|
|||
// late timer fire, where we may begin to run the CC. Should run at least one
|
||||
// early timer fire to allow cleanup before the CC.
|
||||
int32_t numEarlyTimerFires =
|
||||
std::max((int32_t)ccDelay / kCCSkippableDelay - 2, 1);
|
||||
std::max(int32_t(ccDelay / kCCSkippableDelay) - 2, 1);
|
||||
bool isLateTimerFire = sCCRunnerFireCount > numEarlyTimerFires;
|
||||
uint32_t suspected = nsCycleCollector_suspectedCount();
|
||||
if (isLateTimerFire && ShouldTriggerCC(suspected)) {
|
||||
|
@ -2055,7 +2076,7 @@ void nsJSContext::MaybePokeCC() {
|
|||
|
||||
// Don't run consecutive CCs too often.
|
||||
if (sCleanupsSinceLastGC && !sLastCCEndTime.IsNull()) {
|
||||
uint32_t sinceLastCCEnd = TimeUntilNow(sLastCCEndTime);
|
||||
TimeDuration sinceLastCCEnd = TimeUntilNow(sLastCCEndTime);
|
||||
if (sinceLastCCEnd < kCCDelay) {
|
||||
return;
|
||||
}
|
||||
|
@ -2065,7 +2086,7 @@ void nsJSContext::MaybePokeCC() {
|
|||
// don't start a new cycle too soon.
|
||||
if ((sCleanupsSinceLastGC > kMajorForgetSkippableCalls) &&
|
||||
!sLastForgetSkippableCycleEndTime.IsNull()) {
|
||||
uint32_t sinceLastForgetSkippableCycle =
|
||||
TimeDuration sinceLastForgetSkippableCycle =
|
||||
TimeUntilNow(sLastForgetSkippableCycleEndTime);
|
||||
if (sinceLastForgetSkippableCycle < kTimeBetweenForgetSkippableCycles) {
|
||||
return;
|
||||
|
@ -2079,9 +2100,10 @@ void nsJSContext::MaybePokeCC() {
|
|||
nsCycleCollector_dispatchDeferredDeletion();
|
||||
|
||||
sCCRunner = IdleTaskRunner::Create(
|
||||
CCRunnerFired, "MaybePokeCC::CCRunnerFired", kCCSkippableDelay,
|
||||
kForgetSkippableSliceDuration, true, [] { return sShuttingDown; },
|
||||
TaskCategory::GarbageCollection);
|
||||
CCRunnerFired, "MaybePokeCC::CCRunnerFired",
|
||||
kCCSkippableDelay.ToMilliseconds(),
|
||||
kForgetSkippableSliceDuration.ToMilliseconds(), true,
|
||||
[] { return sShuttingDown; }, TaskCategory::GarbageCollection);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2240,7 +2262,7 @@ static void DOMGCSliceCallback(JSContext* aCx, JS::GCProgress aProgress,
|
|||
}
|
||||
|
||||
Telemetry::Accumulate(Telemetry::GC_IN_PROGRESS_MS,
|
||||
TimeBetween(sCurrentGCStartTime, TimeStamp::Now()));
|
||||
TimeUntilNow(sCurrentGCStartTime).ToMilliseconds());
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче