Bug 1870008 - make high rate mode handling dynamic, r=farre

Differential Revision: https://phabricator.services.mozilla.com/D196591
This commit is contained in:
Olli Pettay 2023-12-18 15:40:09 +00:00
Родитель a5466d63d5
Коммит 7acd483571
4 изменённых файлов: 30 добавлений и 24 удалений

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

@ -637,9 +637,10 @@ void CCGCScheduler::EnsureGCRunner(TimeDuration aDelay) {
return; return;
} }
TimeDuration minimumBudget = nsRefreshDriver::IsInHighRateMode() TimeDuration minimumBudget = TimeDuration::FromMilliseconds(
? TimeDuration::FromMilliseconds(1) std::max(nsRefreshDriver::HighRateMultiplier() *
: mActiveIntersliceGCBudget; mActiveIntersliceGCBudget.ToMilliseconds(),
1.0));
// Wait at most the interslice GC delay before forcing a run. // Wait at most the interslice GC delay before forcing a run.
mGCRunner = IdleTaskRunner::Create( mGCRunner = IdleTaskRunner::Create(
@ -702,9 +703,8 @@ void CCGCScheduler::KillGCRunner() {
void CCGCScheduler::EnsureCCRunner(TimeDuration aDelay, TimeDuration aBudget) { void CCGCScheduler::EnsureCCRunner(TimeDuration aDelay, TimeDuration aBudget) {
MOZ_ASSERT(!mDidShutdown); MOZ_ASSERT(!mDidShutdown);
TimeDuration minimumBudget = nsRefreshDriver::IsInHighRateMode() TimeDuration minimumBudget = TimeDuration::FromMilliseconds(std::max(
? TimeDuration::FromMilliseconds(1) nsRefreshDriver::HighRateMultiplier() * aBudget.ToMilliseconds(), 1.0));
: aBudget;
if (!mCCRunner) { if (!mCCRunner) {
mCCRunner = IdleTaskRunner::Create( mCCRunner = IdleTaskRunner::Create(

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

@ -143,6 +143,8 @@ namespace mozilla {
static TimeStamp sMostRecentHighRateVsync; static TimeStamp sMostRecentHighRateVsync;
static TimeDuration sMostRecentHighRate;
/* /*
* The base class for all global refresh driver timers. It takes care * The base class for all global refresh driver timers. It takes care
* of managing the list of refresh drivers attached to them and * of managing the list of refresh drivers attached to them and
@ -233,12 +235,12 @@ class RefreshDriverTimer {
TimeStamp mostRecentRefresh = MostRecentRefresh(); TimeStamp mostRecentRefresh = MostRecentRefresh();
TimeDuration refreshPeriod = GetTimerRate(); TimeDuration refreshPeriod = GetTimerRate();
TimeStamp idleEnd = mostRecentRefresh + refreshPeriod; 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 // 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 // again for a while, so the refresh driver is not a good way to predict
// idle time. // idle time.
if (!inHighRateMode && if (highRateMultiplier == 1.0 &&
(idleEnd + (idleEnd +
refreshPeriod * refreshPeriod *
StaticPrefs::layout_idle_period_required_quiescent_frames() < 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 // End the predicted idle time a little early, the amount controlled by a
// pref, to prevent overrunning the idle time and delaying a frame. // pref, to prevent overrunning the idle time and delaying a frame.
// But do that only if we aren't in high rate mode. // But do that only if we aren't in high rate mode.
idleEnd = idleEnd = idleEnd - TimeDuration::FromMilliseconds(
idleEnd - highRateMultiplier *
TimeDuration::FromMilliseconds( StaticPrefs::layout_idle_period_time_limit());
inHighRateMode ? 0 : StaticPrefs::layout_idle_period_time_limit());
return idleEnd < aDefault ? idleEnd : aDefault; return idleEnd < aDefault ? idleEnd : aDefault;
} }
@ -837,9 +838,10 @@ class VsyncRefreshDriverTimer : public RefreshDriverTimer {
ContentChild::GetPerformanceHintTarget(rate)); ContentChild::GetPerformanceHintTarget(rate));
} }
if (TimeDuration::FromMilliseconds(nsRefreshDriver::DefaultInterval() / 2) > if (TimeDuration::FromMilliseconds(nsRefreshDriver::DefaultInterval()) >
rate) { rate) {
sMostRecentHighRateVsync = tickStart; sMostRecentHighRateVsync = tickStart;
sMostRecentHighRate = rate;
} }
// On 32-bit Windows we sometimes get times where TimeStamp::Now() is not // On 32-bit Windows we sometimes get times where TimeStamp::Now() is not
@ -1257,7 +1259,7 @@ int32_t nsRefreshDriver::DefaultInterval() {
} }
/* static */ /* static */
bool nsRefreshDriver::IsInHighRateMode() { double nsRefreshDriver::HighRateMultiplier() {
// We're in high rate mode if we've gotten a fast rate during the last // We're in high rate mode if we've gotten a fast rate during the last
// DefaultInterval(). // DefaultInterval().
bool inHighRateMode = bool inHighRateMode =
@ -1269,8 +1271,11 @@ bool nsRefreshDriver::IsInHighRateMode() {
if (!inHighRateMode) { if (!inHighRateMode) {
// Clear the timestamp so that the next call is faster. // Clear the timestamp so that the next call is faster.
sMostRecentHighRateVsync = TimeStamp(); 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. // Compute the interval to use for the refresh driver timer, in milliseconds.

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

@ -323,10 +323,12 @@ class nsRefreshDriver final : public mozilla::layers::TransactionIdAllocator,
static int32_t DefaultInterval(); static int32_t DefaultInterval();
/** /**
* Returns true if a recent vsync interval has been less than a half of * Returns 1.0 if a recent rate wasn't smaller than
* DefaultInterval. * DefaultInterval(). Otherwise return rate / DefaultInterval();
* So the return value is (0-1].
*
*/ */
static bool IsInHighRateMode(); static double HighRateMultiplier();
bool IsInRefresh() { return mInRefresh; } bool IsInRefresh() { return mInRefresh; }

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

@ -48,11 +48,9 @@ MainThreadIdlePeriod::GetIdlePeriodHint(TimeStamp* aIdleDeadline) {
// If the idle period is too small, then just return a null time // If the idle period is too small, then just return a null time
// to indicate we are busy. Otherwise return the actual deadline. // to indicate we are busy. Otherwise return the actual deadline.
// double highRateMultiplier = nsRefreshDriver::HighRateMultiplier();
// If we're in high frequency rate mode, idle.period.min isn't used but limit
// is 1.
TimeDuration minIdlePeriod = TimeDuration::FromMilliseconds( TimeDuration minIdlePeriod = TimeDuration::FromMilliseconds(
nsRefreshDriver::IsInHighRateMode() ? 1 : StaticPrefs::idle_period_min()); std::max(highRateMultiplier * StaticPrefs::idle_period_min(), 1.0));
bool busySoon = currentGuess.IsNull() || bool busySoon = currentGuess.IsNull() ||
(now >= (currentGuess - minIdlePeriod)) || (now >= (currentGuess - minIdlePeriod)) ||
currentGuess < mLastIdleDeadline; currentGuess < mLastIdleDeadline;
@ -60,8 +58,9 @@ MainThreadIdlePeriod::GetIdlePeriodHint(TimeStamp* aIdleDeadline) {
// During page load use higher minimum idle period. // During page load use higher minimum idle period.
if (!busySoon && XRE_IsContentProcess() && if (!busySoon && XRE_IsContentProcess() &&
mozilla::dom::Document::HasRecentlyStartedForegroundLoads()) { mozilla::dom::Document::HasRecentlyStartedForegroundLoads()) {
TimeDuration minIdlePeriod = TimeDuration::FromMilliseconds( TimeDuration minIdlePeriod = TimeDuration::FromMilliseconds(std::max(
StaticPrefs::idle_period_during_page_load_min()); highRateMultiplier * StaticPrefs::idle_period_during_page_load_min(),
1.0));
busySoon = (now >= (currentGuess - minIdlePeriod)); busySoon = (now >= (currentGuess - minIdlePeriod));
} }