Diff
Modified: trunk/Source/WebCore/ChangeLog (240943 => 240944)
--- trunk/Source/WebCore/ChangeLog 2019-02-04 22:28:32 UTC (rev 240943)
+++ trunk/Source/WebCore/ChangeLog 2019-02-04 22:30:31 UTC (rev 240944)
@@ -1,3 +1,36 @@
+2019-02-04 Benjamin Poulain <benja...@webkit.org>
+
+ Use deferrable timer to restart the Responsiveness Timer on each wheel event
+ https://bugs.webkit.org/show_bug.cgi?id=194135
+ <rdar://problem/47724099>
+
+ Reviewed by Simon Fraser.
+
+ The original DeferrableOneShotTimer was not really deferrable.
+ What it allows is to restart the count down from scratch after
+ firing.
+
+ For this optimization, I want to keep the correct timing but avoid
+ starting a real timer every time.
+
+ I renamed DeferrableOneShotTimer to ResettableOneShotTimer and
+ created a real DeferrableOneShotTimer that support deadlines.
+
+ * css/CSSImageGeneratorValue.cpp:
+ * html/HTMLPlugInImageElement.h:
+ * loader/cache/CachedResource.h:
+ * platform/Timer.cpp:
+ (WebCore::DeferrableOneShotTimer::startOneShot):
+ (WebCore::DeferrableOneShotTimer::fired):
+ * platform/Timer.h:
+ (WebCore::TimerBase::nextFireTime const):
+ (WebCore::ResettableOneShotTimer::ResettableOneShotTimer):
+ (WebCore::DeferrableOneShotTimer::DeferrableOneShotTimer):
+ (WebCore::DeferrableOneShotTimer::stop):
+ (WebCore::DeferrableOneShotTimer::restart): Deleted.
+ * platform/graphics/ca/TileController.h:
+ * platform/graphics/cg/SubimageCacheWithTimer.h:
+
2019-02-04 Antoine Quint <grao...@apple.com>
Use constants for pointer types
Modified: trunk/Source/WebCore/css/CSSImageGeneratorValue.cpp (240943 => 240944)
--- trunk/Source/WebCore/css/CSSImageGeneratorValue.cpp 2019-02-04 22:28:32 UTC (rev 240943)
+++ trunk/Source/WebCore/css/CSSImageGeneratorValue.cpp 2019-02-04 22:30:31 UTC (rev 240944)
@@ -56,7 +56,7 @@
CSSImageGeneratorValue& m_owner;
const FloatSize m_size;
const Ref<GeneratedImage> m_image;
- DeferrableOneShotTimer m_evictionTimer;
+ ResettableOneShotTimer m_evictionTimer;
};
CSSImageGeneratorValue::CSSImageGeneratorValue(ClassType classType)
Modified: trunk/Source/WebCore/html/HTMLPlugInImageElement.h (240943 => 240944)
--- trunk/Source/WebCore/html/HTMLPlugInImageElement.h 2019-02-04 22:28:32 UTC (rev 240943)
+++ trunk/Source/WebCore/html/HTMLPlugInImageElement.h 2019-02-04 22:30:31 UTC (rev 240944)
@@ -130,7 +130,7 @@
bool m_needsWidgetUpdate { false };
bool m_needsDocumentActivationCallbacks { false };
RefPtr<MouseEvent> m_pendingClickEventFromSnapshot;
- DeferrableOneShotTimer m_simulatedMouseClickTimer;
+ ResettableOneShotTimer m_simulatedMouseClickTimer;
Timer m_removeSnapshotTimer;
RefPtr<Image> m_snapshotImage;
bool m_createdDuringUserGesture { false };
Modified: trunk/Source/WebCore/loader/cache/CachedResource.h (240943 => 240944)
--- trunk/Source/WebCore/loader/cache/CachedResource.h 2019-02-04 22:28:32 UTC (rev 240943)
+++ trunk/Source/WebCore/loader/cache/CachedResource.h 2019-02-04 22:30:31 UTC (rev 240944)
@@ -311,7 +311,7 @@
ResourceRequest m_resourceRequest;
ResourceResponse m_response;
- DeferrableOneShotTimer m_decodedDataDeletionTimer;
+ ResettableOneShotTimer m_decodedDataDeletionTimer;
// FIXME: Make the rest of these data members private and use functions in derived classes instead.
HashCountedSet<CachedResourceClient*> m_clients;
Modified: trunk/Source/WebCore/platform/Timer.cpp (240943 => 240944)
--- trunk/Source/WebCore/platform/Timer.cpp 2019-02-04 22:28:32 UTC (rev 240943)
+++ trunk/Source/WebCore/platform/Timer.cpp 2019-02-04 22:30:31 UTC (rev 240944)
@@ -260,7 +260,7 @@
TimerBase::~TimerBase()
{
- ASSERT(canAccessThreadLocalDataForThread(m_thread.get()));
+ assertThreadSafety();
RELEASE_ASSERT(canAccessThreadLocalDataForThread(m_thread.get()) || shouldSuppressThreadSafetyCheck());
stop();
ASSERT(!inHeap());
@@ -273,7 +273,7 @@
void TimerBase::start(Seconds nextFireInterval, Seconds repeatInterval)
{
- ASSERT(canAccessThreadLocalDataForThread(m_thread.get()));
+ assertThreadSafety();
m_repeatInterval = repeatInterval;
setNextFireTime(MonotonicTime::now() + nextFireInterval);
@@ -281,7 +281,7 @@
void TimerBase::stop()
{
- ASSERT(canAccessThreadLocalDataForThread(m_thread.get()));
+ assertThreadSafety();
m_repeatInterval = 0_s;
setNextFireTime(MonotonicTime { });
@@ -465,7 +465,7 @@
void TimerBase::setNextFireTime(MonotonicTime newTime)
{
- ASSERT(canAccessThreadLocalDataForThread(m_thread.get()));
+ assertThreadSafety();
RELEASE_ASSERT(canAccessThreadLocalDataForThread(m_thread.get()) || shouldSuppressThreadSafetyCheck());
RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(!m_wasDeleted);
@@ -520,5 +520,53 @@
return std::max(m_unalignedNextFireTime - MonotonicTime::now(), 0_s);
}
+DeferrableOneShotTimer::DeferrableOneShotTimer(WTF::Function<void()>&& function)
+ : m_function(WTFMove(function))
+{
+}
+
+DeferrableOneShotTimer::~DeferrableOneShotTimer() = default;
+
+void DeferrableOneShotTimer::startOneShot(Seconds interval)
+{
+ assertThreadSafety();
+
+ MonotonicTime oldNextFireTime = TimerBase::nextFireTime();
+ if (!oldNextFireTime) {
+ m_restartFireTime = MonotonicTime();
+ TimerBase::startOneShot(interval);
+ return;
+ }
+
+ MonotonicTime newNextFireTime = MonotonicTime::now() + interval;
+ if (newNextFireTime < oldNextFireTime) {
+ m_restartFireTime = MonotonicTime();
+ TimerBase::setNextFireTime(newNextFireTime);
+ return;
+ }
+
+ m_restartFireTime = newNextFireTime;
+}
+
+void DeferrableOneShotTimer::stop()
+{
+ TimerBase::stop();
+}
+
+void DeferrableOneShotTimer::fired()
+{
+ if (m_restartFireTime) {
+ MonotonicTime now = MonotonicTime::now();
+ MonotonicTime restartFireTime = m_restartFireTime;
+ m_restartFireTime = MonotonicTime();
+ if (now < restartFireTime) {
+ TimerBase::setNextFireTime(restartFireTime);
+ return;
+ }
+ }
+
+ m_function();
+}
+
} // namespace WebCore
Modified: trunk/Source/WebCore/platform/Timer.h (240943 => 240944)
--- trunk/Source/WebCore/platform/Timer.h 2019-02-04 22:28:32 UTC (rev 240943)
+++ trunk/Source/WebCore/platform/Timer.h 2019-02-04 22:30:31 UTC (rev 240944)
@@ -68,6 +68,15 @@
static void fireTimersInNestedEventLoop();
+protected:
+ MonotonicTime nextFireTime() const { return m_heapItem ? m_heapItem->time : MonotonicTime { }; }
+ void setNextFireTime(MonotonicTime);
+
+ void assertThreadSafety()
+ {
+ ASSERT(canAccessThreadLocalDataForThread(m_thread.get()));
+ }
+
private:
virtual void fired() = 0;
@@ -76,8 +85,6 @@
void checkConsistency() const;
void checkHeapIndex() const;
- void setNextFireTime(MonotonicTime);
-
bool inHeap() const { return m_heapItem && m_heapItem->isInHeap(); }
bool hasValidHeapPosition() const;
@@ -92,8 +99,6 @@
void heapPopMin();
static void heapDeleteNullMin(ThreadTimerHeap&);
- MonotonicTime nextFireTime() const { return m_heapItem ? m_heapItem->time : MonotonicTime { }; }
-
MonotonicTime m_unalignedNextFireTime; // m_nextFireTime not considering alignment interval
Seconds m_repeatInterval; // 0 if not repeating
bool m_wasDeleted { false };
@@ -141,16 +146,29 @@
return static_cast<bool>(nextFireTime());
}
-class DeferrableOneShotTimer : protected TimerBase {
+// ResettableOneShotTimer is a optimization for timers that need to be delayed frequently.
+//
+// Changing the deadline of a timer is not a cheap operation. When it is done frequently, it can
+// affect performance.
+//
+// With ResettableOneShotTimer, calling restart() does not change the underlying timer.
+// Instead, when the underlying timer fires, a new dealine is set for "delay" seconds.
+//
+// When a ResettableOneShotTimer of 5 seconds is restarted before the deadline, the total
+// time before the function is called is 10 seconds.
+//
+// If a timer is unfrequently reset, or if it is usually stopped before the deadline,
+// prefer WebCore::Timer to avoid idle wake-up.
+class ResettableOneShotTimer : protected TimerBase {
WTF_MAKE_FAST_ALLOCATED;
public:
template<typename TimerFiredClass>
- DeferrableOneShotTimer(TimerFiredClass& object, void (TimerFiredClass::*function)(), Seconds delay)
- : DeferrableOneShotTimer(std::bind(function, &object), delay)
+ ResettableOneShotTimer(TimerFiredClass& object, void (TimerFiredClass::*function)(), Seconds delay)
+ : ResettableOneShotTimer(std::bind(function, &object), delay)
{
}
- DeferrableOneShotTimer(WTF::Function<void ()>&& function, Seconds delay)
+ ResettableOneShotTimer(WTF::Function<void()>&& function, Seconds delay)
: m_function(WTFMove(function))
, m_delay(delay)
, m_shouldRestartWhenTimerFires(false)
@@ -196,4 +214,30 @@
bool m_shouldRestartWhenTimerFires;
};
+// DeferrableOneShotTimer is a optimization for timers that need to change the deadline frequently.
+//
+// With DeferrableOneShotTimer, if the new deadline is later than the original deadline, the timer
+// is not reset. Instead, the timer fires and schedule a new timer for the remaining time.
+//
+// DeferrableOneShotTimer supports absolute deadlines.
+// If a timer of 5 seconds is restarted after 2 seconds, the total time will be 7 seconds.
+//
+// Restarting a DeferrableOneShotTimer is more expensive than restarting a ResettableOneShotTimer.
+// If accumulating the delay is not important, prefer ResettableOneShotTimer.
+class WEBCORE_EXPORT DeferrableOneShotTimer : private TimerBase {
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ DeferrableOneShotTimer(WTF::Function<void()>&&);
+ ~DeferrableOneShotTimer();
+
+ void startOneShot(Seconds interval);
+ void stop();
+
+private:
+ void fired() override;
+
+ WTF::Function<void()> m_function;
+ MonotonicTime m_restartFireTime;
+};
+
}
Modified: trunk/Source/WebCore/platform/graphics/ca/TileController.h (240943 => 240944)
--- trunk/Source/WebCore/platform/graphics/ca/TileController.h 2019-02-04 22:28:32 UTC (rev 240943)
+++ trunk/Source/WebCore/platform/graphics/ca/TileController.h 2019-02-04 22:30:31 UTC (rev 240944)
@@ -207,7 +207,7 @@
IntRect m_boundsAtLastRevalidate;
Timer m_tileRevalidationTimer;
- DeferrableOneShotTimer m_tileSizeChangeTimer;
+ ResettableOneShotTimer m_tileSizeChangeTimer;
TileCoverage m_tileCoverage { CoverageForVisibleArea };
Modified: trunk/Source/WebCore/platform/graphics/cg/SubimageCacheWithTimer.h (240943 => 240944)
--- trunk/Source/WebCore/platform/graphics/cg/SubimageCacheWithTimer.h 2019-02-04 22:28:32 UTC (rev 240943)
+++ trunk/Source/WebCore/platform/graphics/cg/SubimageCacheWithTimer.h 2019-02-04 22:30:31 UTC (rev 240944)
@@ -94,7 +94,7 @@
HashCountedSet<CGImageRef> m_images;
SubimageCacheHashSet m_cache;
- DeferrableOneShotTimer m_timer;
+ ResettableOneShotTimer m_timer;
static SubimageCacheWithTimer& subimageCache();
static bool subimageCacheExists();
Modified: trunk/Source/WebKit/ChangeLog (240943 => 240944)
--- trunk/Source/WebKit/ChangeLog 2019-02-04 22:28:32 UTC (rev 240943)
+++ trunk/Source/WebKit/ChangeLog 2019-02-04 22:30:31 UTC (rev 240944)
@@ -1,3 +1,23 @@
+2019-02-04 Benjamin Poulain <benja...@webkit.org>
+
+ Use deferrable timer to restart the Responsiveness Timer on each wheel event
+ https://bugs.webkit.org/show_bug.cgi?id=194135
+
+ Reviewed by Simon Fraser.
+
+ Simon Fraser suggested a neat improvement over my previous optimization
+ of ResponsivenessTimer.
+
+ Instead of reseting the deadline with every event, we can let the timer
+ fire and add the missing time from the last start.
+
+ I implemented that behavior in the new Deferrable Timer class and use
+ it from ResponsivenessTimer.
+
+ * NetworkProcess/watchos/NetworkProximityAssertion.h:
+ * UIProcess/ResponsivenessTimer.h:
+ * WebProcess/Plugins/PluginView.h:
+
2019-02-04 Simon Fraser <simon.fra...@apple.com>
PageOverlayController's layers should be created lazily
Modified: trunk/Source/WebKit/NetworkProcess/watchos/NetworkProximityAssertion.h (240943 => 240944)
--- trunk/Source/WebKit/NetworkProcess/watchos/NetworkProximityAssertion.h 2019-02-04 22:28:32 UTC (rev 240943)
+++ trunk/Source/WebKit/NetworkProcess/watchos/NetworkProximityAssertion.h 2019-02-04 22:30:31 UTC (rev 240944)
@@ -87,8 +87,8 @@
uint64_t m_assertionCount { 0 };
State m_state { State::Suspended };
- WebCore::DeferrableOneShotTimer m_releaseTimer;
- WebCore::DeferrableOneShotTimer m_suspendAfterBackgroundingTimer;
+ WebCore::ResettableOneShotTimer m_releaseTimer;
+ WebCore::ResettableOneShotTimer m_suspendAfterBackgroundingTimer;
};
class BluetoothProximityAssertion final : public NetworkProximityAssertion {
Modified: trunk/Source/WebKit/UIProcess/ResponsivenessTimer.cpp (240943 => 240944)
--- trunk/Source/WebKit/UIProcess/ResponsivenessTimer.cpp 2019-02-04 22:28:32 UTC (rev 240943)
+++ trunk/Source/WebKit/UIProcess/ResponsivenessTimer.cpp 2019-02-04 22:30:31 UTC (rev 240944)
@@ -32,7 +32,7 @@
ResponsivenessTimer::ResponsivenessTimer(ResponsivenessTimer::Client& client)
: m_client(client)
- , m_timer(*this, &ResponsivenessTimer::timerFired)
+ , m_timer(std::bind(&ResponsivenessTimer::timerFired, this))
{
}
Modified: trunk/Source/WebKit/UIProcess/ResponsivenessTimer.h (240943 => 240944)
--- trunk/Source/WebKit/UIProcess/ResponsivenessTimer.h 2019-02-04 22:28:32 UTC (rev 240943)
+++ trunk/Source/WebKit/UIProcess/ResponsivenessTimer.h 2019-02-04 22:30:31 UTC (rev 240944)
@@ -71,7 +71,7 @@
void timerFired();
ResponsivenessTimer::Client& m_client;
- WebCore::Timer m_timer;
+ WebCore::DeferrableOneShotTimer m_timer;
bool m_isResponsive { true };
bool m_waitingForTimer { false };
bool m_useLazyStop { false };
Modified: trunk/Source/WebKit/WebProcess/Plugins/PluginView.h (240943 => 240944)
--- trunk/Source/WebKit/WebProcess/Plugins/PluginView.h 2019-02-04 22:28:32 UTC (rev 240943)
+++ trunk/Source/WebKit/WebProcess/Plugins/PluginView.h 2019-02-04 22:30:31 UTC (rev 240944)
@@ -284,7 +284,7 @@
// This snapshot is used to avoid side effects should the plugin run JS during painting.
RefPtr<ShareableBitmap> m_transientPaintingSnapshot;
// This timer is used when plugin snapshotting is enabled, to capture a plugin placeholder.
- WebCore::DeferrableOneShotTimer m_pluginSnapshotTimer;
+ WebCore::ResettableOneShotTimer m_pluginSnapshotTimer;
#if ENABLE(PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC) || PLATFORM(COCOA)
unsigned m_countSnapshotRetries { 0 };
#endif