diff --git a/dom/base/CCGCScheduler.cpp b/dom/base/CCGCScheduler.cpp index 13f17795daf5..e9313a1d3417 100644 --- a/dom/base/CCGCScheduler.cpp +++ b/dom/base/CCGCScheduler.cpp @@ -637,9 +637,10 @@ void CCGCScheduler::EnsureGCRunner(TimeDuration aDelay) { return; } - TimeDuration minimumBudget = nsRefreshDriver::IsInHighRateMode() - ? TimeDuration::FromMilliseconds(1) - : mActiveIntersliceGCBudget; + TimeDuration minimumBudget = TimeDuration::FromMilliseconds( + std::max(nsRefreshDriver::HighRateMultiplier() * + mActiveIntersliceGCBudget.ToMilliseconds(), + 1.0)); // Wait at most the interslice GC delay before forcing a run. mGCRunner = IdleTaskRunner::Create( @@ -702,9 +703,8 @@ void CCGCScheduler::KillGCRunner() { void CCGCScheduler::EnsureCCRunner(TimeDuration aDelay, TimeDuration aBudget) { MOZ_ASSERT(!mDidShutdown); - TimeDuration minimumBudget = nsRefreshDriver::IsInHighRateMode() - ? TimeDuration::FromMilliseconds(1) - : aBudget; + TimeDuration minimumBudget = TimeDuration::FromMilliseconds(std::max( + nsRefreshDriver::HighRateMultiplier() * aBudget.ToMilliseconds(), 1.0)); if (!mCCRunner) { mCCRunner = IdleTaskRunner::Create( diff --git a/layout/base/nsRefreshDriver.cpp b/layout/base/nsRefreshDriver.cpp index 744bbd0fa434..ae10c19671ba 100644 --- a/layout/base/nsRefreshDriver.cpp +++ b/layout/base/nsRefreshDriver.cpp @@ -143,6 +143,8 @@ namespace mozilla { static TimeStamp sMostRecentHighRateVsync; +static TimeDuration sMostRecentHighRate; + /* * The base class for all global refresh driver timers. It takes care * of managing the list of refresh drivers attached to them and @@ -233,12 +235,12 @@ class RefreshDriverTimer { TimeStamp mostRecentRefresh = MostRecentRefresh(); TimeDuration refreshPeriod = GetTimerRate(); TimeStamp idleEnd = mostRecentRefresh + refreshPeriod; - bool inHighRateMode = nsRefreshDriver::IsInHighRateMode(); + double highRateMultiplier = nsRefreshDriver::HighRateMultiplier(); // If we haven't painted for some time, then guess that we won't paint // again for a while, so the refresh driver is not a good way to predict // idle time. - if (!inHighRateMode && + if (highRateMultiplier == 1.0 && (idleEnd + refreshPeriod * StaticPrefs::layout_idle_period_required_quiescent_frames() < @@ -249,10 +251,9 @@ class RefreshDriverTimer { // End the predicted idle time a little early, the amount controlled by a // pref, to prevent overrunning the idle time and delaying a frame. // But do that only if we aren't in high rate mode. - idleEnd = - idleEnd - - TimeDuration::FromMilliseconds( - inHighRateMode ? 0 : StaticPrefs::layout_idle_period_time_limit()); + idleEnd = idleEnd - TimeDuration::FromMilliseconds( + highRateMultiplier * + StaticPrefs::layout_idle_period_time_limit()); return idleEnd < aDefault ? idleEnd : aDefault; } @@ -837,9 +838,10 @@ class VsyncRefreshDriverTimer : public RefreshDriverTimer { ContentChild::GetPerformanceHintTarget(rate)); } - if (TimeDuration::FromMilliseconds(nsRefreshDriver::DefaultInterval() / 2) > + if (TimeDuration::FromMilliseconds(nsRefreshDriver::DefaultInterval()) > rate) { sMostRecentHighRateVsync = tickStart; + sMostRecentHighRate = rate; } // On 32-bit Windows we sometimes get times where TimeStamp::Now() is not @@ -1257,7 +1259,7 @@ int32_t nsRefreshDriver::DefaultInterval() { } /* static */ -bool nsRefreshDriver::IsInHighRateMode() { +double nsRefreshDriver::HighRateMultiplier() { // We're in high rate mode if we've gotten a fast rate during the last // DefaultInterval(). bool inHighRateMode = @@ -1269,8 +1271,11 @@ bool nsRefreshDriver::IsInHighRateMode() { if (!inHighRateMode) { // Clear the timestamp so that the next call is faster. sMostRecentHighRateVsync = TimeStamp(); + sMostRecentHighRate = TimeDuration(); + return 1.0; } - return inHighRateMode; + + return sMostRecentHighRate.ToMilliseconds() / DefaultInterval(); } // Compute the interval to use for the refresh driver timer, in milliseconds. diff --git a/layout/base/nsRefreshDriver.h b/layout/base/nsRefreshDriver.h index 43edf6d85d61..cd050f74313a 100644 --- a/layout/base/nsRefreshDriver.h +++ b/layout/base/nsRefreshDriver.h @@ -323,10 +323,12 @@ class nsRefreshDriver final : public mozilla::layers::TransactionIdAllocator, static int32_t DefaultInterval(); /** - * Returns true if a recent vsync interval has been less than a half of - * DefaultInterval. + * Returns 1.0 if a recent rate wasn't smaller than + * DefaultInterval(). Otherwise return rate / DefaultInterval(); + * So the return value is (0-1]. + * */ - static bool IsInHighRateMode(); + static double HighRateMultiplier(); bool IsInRefresh() { return mInRefresh; } diff --git a/xpcom/threads/MainThreadIdlePeriod.cpp b/xpcom/threads/MainThreadIdlePeriod.cpp index 432a342ade03..805626dd6758 100644 --- a/xpcom/threads/MainThreadIdlePeriod.cpp +++ b/xpcom/threads/MainThreadIdlePeriod.cpp @@ -48,11 +48,9 @@ MainThreadIdlePeriod::GetIdlePeriodHint(TimeStamp* aIdleDeadline) { // If the idle period is too small, then just return a null time // to indicate we are busy. Otherwise return the actual deadline. - // - // If we're in high frequency rate mode, idle.period.min isn't used but limit - // is 1. + double highRateMultiplier = nsRefreshDriver::HighRateMultiplier(); TimeDuration minIdlePeriod = TimeDuration::FromMilliseconds( - nsRefreshDriver::IsInHighRateMode() ? 1 : StaticPrefs::idle_period_min()); + std::max(highRateMultiplier * StaticPrefs::idle_period_min(), 1.0)); bool busySoon = currentGuess.IsNull() || (now >= (currentGuess - minIdlePeriod)) || currentGuess < mLastIdleDeadline; @@ -60,8 +58,9 @@ MainThreadIdlePeriod::GetIdlePeriodHint(TimeStamp* aIdleDeadline) { // During page load use higher minimum idle period. if (!busySoon && XRE_IsContentProcess() && mozilla::dom::Document::HasRecentlyStartedForegroundLoads()) { - TimeDuration minIdlePeriod = TimeDuration::FromMilliseconds( - StaticPrefs::idle_period_during_page_load_min()); + TimeDuration minIdlePeriod = TimeDuration::FromMilliseconds(std::max( + highRateMultiplier * StaticPrefs::idle_period_during_page_load_min(), + 1.0)); busySoon = (now >= (currentGuess - minIdlePeriod)); }