forked from mirrors/gecko-dev
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:
parent
a8c6527cc9
commit
44faf1c345
11 changed files with 13 additions and 273 deletions
|
|
@ -676,9 +676,6 @@ class VsyncRefreshDriverTimer : public RefreshDriverTimer {
|
|||
void NotifyVsyncOnMainThread(const VsyncEvent& aVsyncEvent) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// This clears the input handling start time.
|
||||
InputTaskManager::Get()->SetInputHandlingStartTime(TimeStamp());
|
||||
|
||||
mRecentVsync = aVsyncEvent.mTime;
|
||||
mRecentVsyncId = aVsyncEvent.mId;
|
||||
if (!mSuspendVsyncPriorityTicksUntil.IsNull() &&
|
||||
|
|
|
|||
|
|
@ -2680,10 +2680,11 @@
|
|||
value: false
|
||||
mirror: always
|
||||
|
||||
# Whether we perform a more strict alignment with vsync for input events
|
||||
- name: dom.input_events.strict_input_vsync_alignment
|
||||
type: bool
|
||||
value: true
|
||||
# The maximum time (milliseconds) we reserve for handling input events in each
|
||||
# frame.
|
||||
- name: dom.input_event_queue.duration.max
|
||||
type: uint32_t
|
||||
value: 8
|
||||
mirror: always
|
||||
|
||||
# Enable not moving the cursor to end when a text input or textarea has .value
|
||||
|
|
|
|||
|
|
@ -2073,19 +2073,6 @@ pref("dom.global_stop_script", true);
|
|||
// Support the input event queue on the main thread of content process
|
||||
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
|
||||
pref("plugins.navigator.hidden_ctp_plugin", "");
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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_
|
||||
|
|
@ -5,7 +5,6 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "InputTaskManager.h"
|
||||
#include "InputEventStatistics.h"
|
||||
#include "VsyncTaskManager.h"
|
||||
#include "nsRefreshDriver.h"
|
||||
|
||||
|
|
@ -17,7 +16,6 @@ void InputTaskManager::EnableInputEventPrioritization() {
|
|||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mInputQueueState == STATE_DISABLED);
|
||||
mInputQueueState = STATE_ENABLED;
|
||||
mInputHandlingStartTime = TimeStamp();
|
||||
}
|
||||
|
||||
void InputTaskManager::FlushInputEventPrioritization() {
|
||||
|
|
@ -53,47 +51,16 @@ int32_t InputTaskManager::GetPriorityModifierForEventLoopTurn(
|
|||
static_cast<int32_t>(EventQueuePriority::InputHigh);
|
||||
}
|
||||
|
||||
if (StaticPrefs::dom_input_events_strict_input_vsync_alignment()) {
|
||||
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() {
|
||||
TaskManager::WillRunTask();
|
||||
mStartTimes.AppendElement(TimeStamp::Now());
|
||||
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
|
||||
InputTaskManager::GetPriorityModifierForEventLoopTurnForStrictVsyncAlignment() {
|
||||
MOZ_ASSERT(StaticPrefs::dom_input_events_strict_input_vsync_alignment());
|
||||
MOZ_ASSERT(!IsSuspended());
|
||||
|
||||
size_t inputCount = PendingTaskCount();
|
||||
|
|
@ -113,20 +80,10 @@ InputTaskManager::GetPriorityModifierForEventLoopTurnForStrictVsyncAlignment() {
|
|||
}
|
||||
|
||||
InputTaskManager::InputPriorityController::InputPriorityController()
|
||||
: mIsInitialized(false),
|
||||
mInputVsyncState(InputVsyncState::NoPendingVsync) {}
|
||||
: mInputVsyncState(InputVsyncState::NoPendingVsync) {}
|
||||
|
||||
bool InputTaskManager::InputPriorityController::ShouldUseHighestPriority(
|
||||
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) {
|
||||
return true;
|
||||
}
|
||||
|
|
@ -146,7 +103,6 @@ bool InputTaskManager::InputPriorityController::ShouldUseHighestPriority(
|
|||
|
||||
void InputTaskManager::InputPriorityController::EnterPendingVsyncState(
|
||||
uint32_t aNumPendingTasks) {
|
||||
MOZ_ASSERT(StaticPrefs::dom_input_events_strict_input_vsync_alignment());
|
||||
MOZ_ASSERT(mInputVsyncState == InputVsyncState::NoPendingVsync);
|
||||
|
||||
mInputVsyncState = InputVsyncState::HasPendingVsync;
|
||||
|
|
@ -155,8 +111,6 @@ void InputTaskManager::InputPriorityController::EnterPendingVsyncState(
|
|||
}
|
||||
|
||||
void InputTaskManager::InputPriorityController::WillRunVsync() {
|
||||
MOZ_ASSERT(StaticPrefs::dom_input_events_strict_input_vsync_alignment());
|
||||
|
||||
if (mInputVsyncState == InputVsyncState::RunVsync ||
|
||||
mInputVsyncState == InputVsyncState::HasPendingVsync) {
|
||||
LeavePendingVsyncState(false);
|
||||
|
|
@ -165,8 +119,6 @@ void InputTaskManager::InputPriorityController::WillRunVsync() {
|
|||
|
||||
void InputTaskManager::InputPriorityController::LeavePendingVsyncState(
|
||||
bool aRunVsync) {
|
||||
MOZ_ASSERT(StaticPrefs::dom_input_events_strict_input_vsync_alignment());
|
||||
|
||||
if (aRunVsync) {
|
||||
MOZ_ASSERT(mInputVsyncState == InputVsyncState::HasPendingVsync);
|
||||
mInputVsyncState = InputVsyncState::RunVsync;
|
||||
|
|
@ -178,8 +130,6 @@ void InputTaskManager::InputPriorityController::LeavePendingVsyncState(
|
|||
}
|
||||
|
||||
void InputTaskManager::InputPriorityController::WillRunTask() {
|
||||
MOZ_ASSERT(StaticPrefs::dom_input_events_strict_input_vsync_alignment());
|
||||
|
||||
switch (mInputVsyncState) {
|
||||
case InputVsyncState::NoPendingVsync:
|
||||
return;
|
||||
|
|
@ -187,7 +137,9 @@ void InputTaskManager::InputPriorityController::WillRunTask() {
|
|||
MOZ_ASSERT(mMaxInputTasksToRun > 0);
|
||||
--mMaxInputTasksToRun;
|
||||
if (!mMaxInputTasksToRun ||
|
||||
TimeStamp::Now() - mRunInputStartTime >= mMaxInputHandlingDuration) {
|
||||
TimeStamp::Now() - mRunInputStartTime >=
|
||||
TimeDuration::FromMilliseconds(
|
||||
StaticPrefs::dom_input_event_queue_duration_max())) {
|
||||
LeavePendingVsyncState(true);
|
||||
}
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ class InputTaskManager : public TaskManager {
|
|||
int32_t GetPriorityModifierForEventLoopTurn(
|
||||
const MutexAutoLock& aProofOfLock) final;
|
||||
void WillRunTask() final;
|
||||
void DidRunTask() final;
|
||||
|
||||
enum InputEventQueueState {
|
||||
STATE_DISABLED,
|
||||
|
|
@ -38,12 +37,6 @@ class InputTaskManager : public TaskManager {
|
|||
|
||||
void SetState(InputEventQueueState aState) { mInputQueueState = aState; }
|
||||
|
||||
TimeStamp InputHandlingStartTime() { return mInputHandlingStartTime; }
|
||||
|
||||
void SetInputHandlingStartTime(TimeStamp aStartTime) {
|
||||
mInputHandlingStartTime = aStartTime;
|
||||
}
|
||||
|
||||
static InputTaskManager* Get() { return gInputTaskManager.get(); }
|
||||
static void Cleanup() { gInputTaskManager = nullptr; }
|
||||
static void Init();
|
||||
|
|
@ -81,10 +74,7 @@ class InputTaskManager : public TaskManager {
|
|||
InputEventQueueState::STATE_DISABLED;
|
||||
}
|
||||
|
||||
void NotifyVsync() {
|
||||
MOZ_ASSERT(StaticPrefs::dom_input_events_strict_input_vsync_alignment());
|
||||
mInputPriorityController.WillRunVsync();
|
||||
}
|
||||
void NotifyVsync() { mInputPriorityController.WillRunVsync(); }
|
||||
|
||||
private:
|
||||
InputTaskManager() : mInputQueueState(STATE_DISABLED) {}
|
||||
|
|
@ -129,18 +119,14 @@ class InputTaskManager : public TaskManager {
|
|||
// InputVsyncState::HasPendingVsync state.
|
||||
uint32_t mMaxInputTasksToRun = 0;
|
||||
|
||||
bool mIsInitialized;
|
||||
InputVsyncState mInputVsyncState;
|
||||
|
||||
TimeStamp mRunInputStartTime;
|
||||
TimeDuration mMaxInputHandlingDuration;
|
||||
};
|
||||
|
||||
int32_t GetPriorityModifierForEventLoopTurnForStrictVsyncAlignment();
|
||||
|
||||
TimeStamp mInputHandlingStartTime;
|
||||
Atomic<InputEventQueueState> mInputQueueState;
|
||||
AutoTArray<TimeStamp, 4> mStartTimes;
|
||||
|
||||
static StaticRefPtr<InputTaskManager> gInputTaskManager;
|
||||
|
||||
|
|
|
|||
|
|
@ -17,9 +17,6 @@ void VsyncTaskManager::Init() {
|
|||
|
||||
void VsyncTaskManager::WillRunTask() {
|
||||
TaskManager::WillRunTask();
|
||||
|
||||
if (StaticPrefs::dom_input_events_strict_input_vsync_alignment()) {
|
||||
InputTaskManager::Get()->NotifyVsync();
|
||||
}
|
||||
};
|
||||
} // namespace mozilla
|
||||
|
|
|
|||
|
|
@ -96,7 +96,6 @@ UNIFIED_SOURCES += [
|
|||
"DelayedRunnable.cpp",
|
||||
"EventQueue.cpp",
|
||||
"IdlePeriodState.cpp",
|
||||
"InputEventStatistics.cpp",
|
||||
"InputTaskManager.cpp",
|
||||
"LazyIdleThread.cpp",
|
||||
"MainThreadIdlePeriod.cpp",
|
||||
|
|
|
|||
|
|
@ -47,7 +47,6 @@
|
|||
#include "nsThreadSyncDispatch.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "GeckoProfiler.h"
|
||||
#include "InputEventStatistics.h"
|
||||
#include "ThreadEventQueue.h"
|
||||
#include "ThreadEventTarget.h"
|
||||
#include "ThreadDelay.h"
|
||||
|
|
|
|||
|
|
@ -35,7 +35,6 @@
|
|||
#endif
|
||||
|
||||
#include "MainThreadIdlePeriod.h"
|
||||
#include "InputEventStatistics.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
|
|
@ -731,7 +730,6 @@ nsThreadManager::DispatchToMainThreadWithMicroTask(nsIRunnable* aEvent,
|
|||
|
||||
void nsThreadManager::EnableMainThreadEventPrioritization() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
InputEventStatistics::Get().SetEnable(true);
|
||||
InputTaskManager::Get()->EnableInputEventPrioritization();
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue