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;
}
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(

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

@ -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.

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

@ -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; }

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

@ -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));
}