Bug 1795624 - remove dom.input_events.strict_input_vsync_alignment, r=sefeng

Had to rename input_event_queue.supported to dom.input_event_queue.supported so that
it could be used as a static pref.

Differential Revision: https://phabricator.services.mozilla.com/D159488
This commit is contained in:
Olli Pettay 2022-10-17 17:02:24 +00:00
parent a8c6527cc9
commit 44faf1c345
11 changed files with 13 additions and 273 deletions

View file

@ -676,9 +676,6 @@ class VsyncRefreshDriverTimer : public RefreshDriverTimer {
void NotifyVsyncOnMainThread(const VsyncEvent& aVsyncEvent) { void NotifyVsyncOnMainThread(const VsyncEvent& aVsyncEvent) {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
// This clears the input handling start time.
InputTaskManager::Get()->SetInputHandlingStartTime(TimeStamp());
mRecentVsync = aVsyncEvent.mTime; mRecentVsync = aVsyncEvent.mTime;
mRecentVsyncId = aVsyncEvent.mId; mRecentVsyncId = aVsyncEvent.mId;
if (!mSuspendVsyncPriorityTicksUntil.IsNull() && if (!mSuspendVsyncPriorityTicksUntil.IsNull() &&

View file

@ -2680,10 +2680,11 @@
value: false value: false
mirror: always mirror: always
# Whether we perform a more strict alignment with vsync for input events # The maximum time (milliseconds) we reserve for handling input events in each
- name: dom.input_events.strict_input_vsync_alignment # frame.
type: bool - name: dom.input_event_queue.duration.max
value: true type: uint32_t
value: 8
mirror: always mirror: always
# Enable not moving the cursor to end when a text input or textarea has .value # Enable not moving the cursor to end when a text input or textarea has .value

View file

@ -2073,19 +2073,6 @@ pref("dom.global_stop_script", true);
// Support the input event queue on the main thread of content process // Support the input event queue on the main thread of content process
pref("input_event_queue.supported", true); pref("input_event_queue.supported", true);
// The maximum and minimum time (milliseconds) we reserve for handling input
// events in each frame.
pref("input_event_queue.duration.max", 8);
pref("input_event_queue.duration.min", 1);
// The default amount of time (milliseconds) required for handling a input
// event.
pref("input_event_queue.default_duration_per_event", 1);
// The number of processed input events we use to predict the amount of time
// required to process the following input events.
pref("input_event_queue.count_for_prediction", 9);
// This only supports one hidden ctp plugin, edit nsPluginArray.cpp if adding a second // This only supports one hidden ctp plugin, edit nsPluginArray.cpp if adding a second
pref("plugins.navigator.hidden_ctp_plugin", ""); pref("plugins.navigator.hidden_ctp_plugin", "");

View file

@ -1,73 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "InputEventStatistics.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/Preferences.h"
#include "nsRefreshDriver.h"
namespace mozilla {
/*static*/ InputEventStatistics& InputEventStatistics::Get() {
static UniquePtr<InputEventStatistics> sInstance;
if (!sInstance) {
sInstance = MakeUnique<InputEventStatistics>(ConstructorCookie());
ClearOnShutdown(&sInstance);
}
return *sInstance;
}
TimeDuration InputEventStatistics::TimeDurationCircularBuffer::GetMean() {
return mTotal / (int64_t)mSize;
}
InputEventStatistics::InputEventStatistics(ConstructorCookie&&)
: mEnable(false) {
MOZ_ASSERT(Preferences::IsServiceAvailable());
uint32_t inputDuration = Preferences::GetUint(
"input_event_queue.default_duration_per_event", sDefaultInputDuration);
TimeDuration defaultDuration = TimeDuration::FromMilliseconds(inputDuration);
uint32_t count = Preferences::GetUint(
"input_event_queue.count_for_prediction", sInputCountForPrediction);
mLastInputDurations =
MakeUnique<TimeDurationCircularBuffer>(count, defaultDuration);
uint32_t maxDuration = Preferences::GetUint("input_event_queue.duration.max",
sMaxReservedTimeForHandlingInput);
uint32_t minDuration = Preferences::GetUint("input_event_queue.duration.min",
sMinReservedTimeForHandlingInput);
mMaxInputDuration = TimeDuration::FromMilliseconds(maxDuration);
mMinInputDuration = TimeDuration::FromMilliseconds(minDuration);
}
TimeStamp InputEventStatistics::GetInputHandlingStartTime(
uint32_t aInputCount) {
MOZ_ASSERT(mEnable);
Maybe<TimeStamp> nextTickHint = nsRefreshDriver::GetNextTickHint();
if (nextTickHint.isNothing()) {
// Return a past time to process input events immediately.
return TimeStamp::Now() - TimeDuration::FromMilliseconds(1);
}
TimeDuration inputCost = mLastInputDurations->GetMean() * aInputCount;
inputCost = inputCost > mMaxInputDuration ? mMaxInputDuration
: inputCost < mMinInputDuration ? mMinInputDuration
: inputCost;
return nextTickHint.value() - inputCost;
}
TimeDuration InputEventStatistics::GetMaxInputHandlingDuration() const {
MOZ_ASSERT(StaticPrefs::dom_input_events_strict_input_vsync_alignment());
return mMaxInputDuration;
}
} // namespace mozilla

View file

@ -1,103 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#if !defined(InputEventStatistics_h_)
# define InputEventStatistics_h_
# include "mozilla/TimeStamp.h"
# include "mozilla/UniquePtr.h"
# include "nsTArray.h"
namespace mozilla {
class InputEventStatistics {
// The default amount of time (milliseconds) required for handling a input
// event.
static const uint16_t sDefaultInputDuration = 1;
// The number of processed input events we use to predict the amount of time
// required to process the following input events.
static const uint16_t sInputCountForPrediction = 9;
// The default maximum and minimum time (milliseconds) we reserve for handling
// input events in each frame.
static const uint16_t sMaxReservedTimeForHandlingInput = 8;
static const uint16_t sMinReservedTimeForHandlingInput = 1;
class TimeDurationCircularBuffer {
int16_t mSize;
int16_t mCurrentIndex;
nsTArray<TimeDuration> mBuffer;
TimeDuration mTotal;
public:
TimeDurationCircularBuffer(uint32_t aSize, TimeDuration& aDefaultValue)
: mSize(aSize), mCurrentIndex(0) {
mSize = mSize == 0 ? sInputCountForPrediction : mSize;
for (int16_t index = 0; index < mSize; ++index) {
mBuffer.AppendElement(aDefaultValue);
mTotal += aDefaultValue;
}
}
void Insert(TimeDuration& aDuration) {
mTotal += (aDuration - mBuffer[mCurrentIndex]);
mBuffer[mCurrentIndex++] = aDuration;
if (mCurrentIndex == mSize) {
mCurrentIndex = 0;
}
}
TimeDuration GetMean();
};
UniquePtr<TimeDurationCircularBuffer> mLastInputDurations;
TimeDuration mMaxInputDuration;
TimeDuration mMinInputDuration;
bool mEnable;
// We'd like to have our constructor and destructor be private to enforce our
// singleton, but because UniquePtr needs to be able to destruct our class we
// can't. This is a trick that ensures that we're the only code that can
// construct ourselves: nobody else can access ConstructorCookie and therefore
// nobody else can construct an InputEventStatistics.
struct ConstructorCookie {};
public:
explicit InputEventStatistics(ConstructorCookie&&);
~InputEventStatistics() = default;
static InputEventStatistics& Get();
void UpdateInputDuration(TimeDuration aDuration) {
if (!mEnable) {
return;
}
mLastInputDurations->Insert(aDuration);
}
TimeStamp GetInputHandlingStartTime(uint32_t aInputCount);
TimeDuration GetMaxInputHandlingDuration() const;
void SetEnable(bool aEnable) { mEnable = aEnable; }
};
class MOZ_RAII AutoTimeDurationHelper final {
public:
AutoTimeDurationHelper() { mStartTime = TimeStamp::Now(); }
~AutoTimeDurationHelper() {
InputEventStatistics::Get().UpdateInputDuration(TimeStamp::Now() -
mStartTime);
}
private:
TimeStamp mStartTime;
};
} // namespace mozilla
#endif // InputEventStatistics_h_

View file

@ -5,7 +5,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "InputTaskManager.h" #include "InputTaskManager.h"
#include "InputEventStatistics.h"
#include "VsyncTaskManager.h" #include "VsyncTaskManager.h"
#include "nsRefreshDriver.h" #include "nsRefreshDriver.h"
@ -17,7 +16,6 @@ void InputTaskManager::EnableInputEventPrioritization() {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mInputQueueState == STATE_DISABLED); MOZ_ASSERT(mInputQueueState == STATE_DISABLED);
mInputQueueState = STATE_ENABLED; mInputQueueState = STATE_ENABLED;
mInputHandlingStartTime = TimeStamp();
} }
void InputTaskManager::FlushInputEventPrioritization() { void InputTaskManager::FlushInputEventPrioritization() {
@ -53,47 +51,16 @@ int32_t InputTaskManager::GetPriorityModifierForEventLoopTurn(
static_cast<int32_t>(EventQueuePriority::InputHigh); static_cast<int32_t>(EventQueuePriority::InputHigh);
} }
if (StaticPrefs::dom_input_events_strict_input_vsync_alignment()) { return GetPriorityModifierForEventLoopTurnForStrictVsyncAlignment();
return GetPriorityModifierForEventLoopTurnForStrictVsyncAlignment();
}
size_t inputCount = PendingTaskCount();
if (State() == STATE_ENABLED && InputHandlingStartTime().IsNull() &&
inputCount > 0) {
SetInputHandlingStartTime(
InputEventStatistics::Get().GetInputHandlingStartTime(inputCount));
}
if (inputCount > 0 && (State() == InputTaskManager::STATE_FLUSHING ||
(State() == InputTaskManager::STATE_ENABLED &&
!InputHandlingStartTime().IsNull() &&
TimeStamp::Now() > InputHandlingStartTime()))) {
return 0;
}
int32_t modifier = static_cast<int32_t>(EventQueuePriority::InputLow) -
static_cast<int32_t>(EventQueuePriority::MediumHigh);
return modifier;
} }
void InputTaskManager::WillRunTask() { void InputTaskManager::WillRunTask() {
TaskManager::WillRunTask(); TaskManager::WillRunTask();
mStartTimes.AppendElement(TimeStamp::Now()); mInputPriorityController.WillRunTask();
if (StaticPrefs::dom_input_events_strict_input_vsync_alignment()) {
mInputPriorityController.WillRunTask();
}
}
void InputTaskManager::DidRunTask() {
TaskManager::DidRunTask();
MOZ_ASSERT(!mStartTimes.IsEmpty());
TimeStamp start = mStartTimes.PopLastElement();
InputEventStatistics::Get().UpdateInputDuration(TimeStamp::Now() - start);
} }
int32_t int32_t
InputTaskManager::GetPriorityModifierForEventLoopTurnForStrictVsyncAlignment() { InputTaskManager::GetPriorityModifierForEventLoopTurnForStrictVsyncAlignment() {
MOZ_ASSERT(StaticPrefs::dom_input_events_strict_input_vsync_alignment());
MOZ_ASSERT(!IsSuspended()); MOZ_ASSERT(!IsSuspended());
size_t inputCount = PendingTaskCount(); size_t inputCount = PendingTaskCount();
@ -113,20 +80,10 @@ InputTaskManager::GetPriorityModifierForEventLoopTurnForStrictVsyncAlignment() {
} }
InputTaskManager::InputPriorityController::InputPriorityController() InputTaskManager::InputPriorityController::InputPriorityController()
: mIsInitialized(false), : mInputVsyncState(InputVsyncState::NoPendingVsync) {}
mInputVsyncState(InputVsyncState::NoPendingVsync) {}
bool InputTaskManager::InputPriorityController::ShouldUseHighestPriority( bool InputTaskManager::InputPriorityController::ShouldUseHighestPriority(
InputTaskManager* aInputTaskManager) { InputTaskManager* aInputTaskManager) {
if (!mIsInitialized) {
// Have to initialize mMaxInputHandlingDuration lazily because
// Preference may not be ready upon the construction of
// InputTaskManager.
mMaxInputHandlingDuration =
InputEventStatistics::Get().GetMaxInputHandlingDuration();
mIsInitialized = true;
}
if (mInputVsyncState == InputVsyncState::HasPendingVsync) { if (mInputVsyncState == InputVsyncState::HasPendingVsync) {
return true; return true;
} }
@ -146,7 +103,6 @@ bool InputTaskManager::InputPriorityController::ShouldUseHighestPriority(
void InputTaskManager::InputPriorityController::EnterPendingVsyncState( void InputTaskManager::InputPriorityController::EnterPendingVsyncState(
uint32_t aNumPendingTasks) { uint32_t aNumPendingTasks) {
MOZ_ASSERT(StaticPrefs::dom_input_events_strict_input_vsync_alignment());
MOZ_ASSERT(mInputVsyncState == InputVsyncState::NoPendingVsync); MOZ_ASSERT(mInputVsyncState == InputVsyncState::NoPendingVsync);
mInputVsyncState = InputVsyncState::HasPendingVsync; mInputVsyncState = InputVsyncState::HasPendingVsync;
@ -155,8 +111,6 @@ void InputTaskManager::InputPriorityController::EnterPendingVsyncState(
} }
void InputTaskManager::InputPriorityController::WillRunVsync() { void InputTaskManager::InputPriorityController::WillRunVsync() {
MOZ_ASSERT(StaticPrefs::dom_input_events_strict_input_vsync_alignment());
if (mInputVsyncState == InputVsyncState::RunVsync || if (mInputVsyncState == InputVsyncState::RunVsync ||
mInputVsyncState == InputVsyncState::HasPendingVsync) { mInputVsyncState == InputVsyncState::HasPendingVsync) {
LeavePendingVsyncState(false); LeavePendingVsyncState(false);
@ -165,8 +119,6 @@ void InputTaskManager::InputPriorityController::WillRunVsync() {
void InputTaskManager::InputPriorityController::LeavePendingVsyncState( void InputTaskManager::InputPriorityController::LeavePendingVsyncState(
bool aRunVsync) { bool aRunVsync) {
MOZ_ASSERT(StaticPrefs::dom_input_events_strict_input_vsync_alignment());
if (aRunVsync) { if (aRunVsync) {
MOZ_ASSERT(mInputVsyncState == InputVsyncState::HasPendingVsync); MOZ_ASSERT(mInputVsyncState == InputVsyncState::HasPendingVsync);
mInputVsyncState = InputVsyncState::RunVsync; mInputVsyncState = InputVsyncState::RunVsync;
@ -178,8 +130,6 @@ void InputTaskManager::InputPriorityController::LeavePendingVsyncState(
} }
void InputTaskManager::InputPriorityController::WillRunTask() { void InputTaskManager::InputPriorityController::WillRunTask() {
MOZ_ASSERT(StaticPrefs::dom_input_events_strict_input_vsync_alignment());
switch (mInputVsyncState) { switch (mInputVsyncState) {
case InputVsyncState::NoPendingVsync: case InputVsyncState::NoPendingVsync:
return; return;
@ -187,7 +137,9 @@ void InputTaskManager::InputPriorityController::WillRunTask() {
MOZ_ASSERT(mMaxInputTasksToRun > 0); MOZ_ASSERT(mMaxInputTasksToRun > 0);
--mMaxInputTasksToRun; --mMaxInputTasksToRun;
if (!mMaxInputTasksToRun || if (!mMaxInputTasksToRun ||
TimeStamp::Now() - mRunInputStartTime >= mMaxInputHandlingDuration) { TimeStamp::Now() - mRunInputStartTime >=
TimeDuration::FromMilliseconds(
StaticPrefs::dom_input_event_queue_duration_max())) {
LeavePendingVsyncState(true); LeavePendingVsyncState(true);
} }
return; return;

View file

@ -20,7 +20,6 @@ class InputTaskManager : public TaskManager {
int32_t GetPriorityModifierForEventLoopTurn( int32_t GetPriorityModifierForEventLoopTurn(
const MutexAutoLock& aProofOfLock) final; const MutexAutoLock& aProofOfLock) final;
void WillRunTask() final; void WillRunTask() final;
void DidRunTask() final;
enum InputEventQueueState { enum InputEventQueueState {
STATE_DISABLED, STATE_DISABLED,
@ -38,12 +37,6 @@ class InputTaskManager : public TaskManager {
void SetState(InputEventQueueState aState) { mInputQueueState = aState; } void SetState(InputEventQueueState aState) { mInputQueueState = aState; }
TimeStamp InputHandlingStartTime() { return mInputHandlingStartTime; }
void SetInputHandlingStartTime(TimeStamp aStartTime) {
mInputHandlingStartTime = aStartTime;
}
static InputTaskManager* Get() { return gInputTaskManager.get(); } static InputTaskManager* Get() { return gInputTaskManager.get(); }
static void Cleanup() { gInputTaskManager = nullptr; } static void Cleanup() { gInputTaskManager = nullptr; }
static void Init(); static void Init();
@ -81,10 +74,7 @@ class InputTaskManager : public TaskManager {
InputEventQueueState::STATE_DISABLED; InputEventQueueState::STATE_DISABLED;
} }
void NotifyVsync() { void NotifyVsync() { mInputPriorityController.WillRunVsync(); }
MOZ_ASSERT(StaticPrefs::dom_input_events_strict_input_vsync_alignment());
mInputPriorityController.WillRunVsync();
}
private: private:
InputTaskManager() : mInputQueueState(STATE_DISABLED) {} InputTaskManager() : mInputQueueState(STATE_DISABLED) {}
@ -129,18 +119,14 @@ class InputTaskManager : public TaskManager {
// InputVsyncState::HasPendingVsync state. // InputVsyncState::HasPendingVsync state.
uint32_t mMaxInputTasksToRun = 0; uint32_t mMaxInputTasksToRun = 0;
bool mIsInitialized;
InputVsyncState mInputVsyncState; InputVsyncState mInputVsyncState;
TimeStamp mRunInputStartTime; TimeStamp mRunInputStartTime;
TimeDuration mMaxInputHandlingDuration;
}; };
int32_t GetPriorityModifierForEventLoopTurnForStrictVsyncAlignment(); int32_t GetPriorityModifierForEventLoopTurnForStrictVsyncAlignment();
TimeStamp mInputHandlingStartTime;
Atomic<InputEventQueueState> mInputQueueState; Atomic<InputEventQueueState> mInputQueueState;
AutoTArray<TimeStamp, 4> mStartTimes;
static StaticRefPtr<InputTaskManager> gInputTaskManager; static StaticRefPtr<InputTaskManager> gInputTaskManager;

View file

@ -17,9 +17,6 @@ void VsyncTaskManager::Init() {
void VsyncTaskManager::WillRunTask() { void VsyncTaskManager::WillRunTask() {
TaskManager::WillRunTask(); TaskManager::WillRunTask();
InputTaskManager::Get()->NotifyVsync();
if (StaticPrefs::dom_input_events_strict_input_vsync_alignment()) {
InputTaskManager::Get()->NotifyVsync();
}
}; };
} // namespace mozilla } // namespace mozilla

View file

@ -96,7 +96,6 @@ UNIFIED_SOURCES += [
"DelayedRunnable.cpp", "DelayedRunnable.cpp",
"EventQueue.cpp", "EventQueue.cpp",
"IdlePeriodState.cpp", "IdlePeriodState.cpp",
"InputEventStatistics.cpp",
"InputTaskManager.cpp", "InputTaskManager.cpp",
"LazyIdleThread.cpp", "LazyIdleThread.cpp",
"MainThreadIdlePeriod.cpp", "MainThreadIdlePeriod.cpp",

View file

@ -47,7 +47,6 @@
#include "nsThreadSyncDispatch.h" #include "nsThreadSyncDispatch.h"
#include "nsServiceManagerUtils.h" #include "nsServiceManagerUtils.h"
#include "GeckoProfiler.h" #include "GeckoProfiler.h"
#include "InputEventStatistics.h"
#include "ThreadEventQueue.h" #include "ThreadEventQueue.h"
#include "ThreadEventTarget.h" #include "ThreadEventTarget.h"
#include "ThreadDelay.h" #include "ThreadDelay.h"

View file

@ -35,7 +35,6 @@
#endif #endif
#include "MainThreadIdlePeriod.h" #include "MainThreadIdlePeriod.h"
#include "InputEventStatistics.h"
using namespace mozilla; using namespace mozilla;
@ -731,7 +730,6 @@ nsThreadManager::DispatchToMainThreadWithMicroTask(nsIRunnable* aEvent,
void nsThreadManager::EnableMainThreadEventPrioritization() { void nsThreadManager::EnableMainThreadEventPrioritization() {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
InputEventStatistics::Get().SetEnable(true);
InputTaskManager::Get()->EnableInputEventPrioritization(); InputTaskManager::Get()->EnableInputEventPrioritization();
} }