⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 240944 in webkit


Ignore:
Timestamp:
Feb 4, 2019, 2:30:31 PM (8 years ago)
Author:
benjamin@webkit.org
Message:

Use deferrable timer to restart the Responsiveness Timer on each wheel event
https://bugs.webkit.org/show_bug.cgi?id=194135
Source/WebCore:

<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:

Source/WebKit:

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:
Location:
trunk/Source
Files:
13 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r240943 r240944  
     12019-02-04  Benjamin Poulain  <benjamin@webkit.org>
     2
     3        Use deferrable timer to restart the Responsiveness Timer on each wheel event
     4        https://bugs.webkit.org/show_bug.cgi?id=194135
     5        <rdar://problem/47724099>
     6
     7        Reviewed by Simon Fraser.
     8
     9        The original DeferrableOneShotTimer was not really deferrable.
     10        What it allows is to restart the count down from scratch after
     11        firing.
     12
     13        For this optimization, I want to keep the correct timing but avoid
     14        starting a real timer every time.
     15
     16        I renamed DeferrableOneShotTimer to ResettableOneShotTimer and
     17        created a real DeferrableOneShotTimer that support deadlines.
     18
     19        * css/CSSImageGeneratorValue.cpp:
     20        * html/HTMLPlugInImageElement.h:
     21        * loader/cache/CachedResource.h:
     22        * platform/Timer.cpp:
     23        (WebCore::DeferrableOneShotTimer::startOneShot):
     24        (WebCore::DeferrableOneShotTimer::fired):
     25        * platform/Timer.h:
     26        (WebCore::TimerBase::nextFireTime const):
     27        (WebCore::ResettableOneShotTimer::ResettableOneShotTimer):
     28        (WebCore::DeferrableOneShotTimer::DeferrableOneShotTimer):
     29        (WebCore::DeferrableOneShotTimer::stop):
     30        (WebCore::DeferrableOneShotTimer::restart): Deleted.
     31        * platform/graphics/ca/TileController.h:
     32        * platform/graphics/cg/SubimageCacheWithTimer.h:
     33
    1342019-02-04  Antoine Quint  <graouts@apple.com>
    235
  • trunk/Source/WebCore/css/CSSImageGeneratorValue.cpp

    r237276 r240944  
    5757    const FloatSize m_size;
    5858    const Ref<GeneratedImage> m_image;
    59     DeferrableOneShotTimer m_evictionTimer;
     59    ResettableOneShotTimer m_evictionTimer;
    6060};
    6161
  • trunk/Source/WebCore/html/HTMLPlugInImageElement.h

    r229694 r240944  
    131131    bool m_needsDocumentActivationCallbacks { false };
    132132    RefPtr<MouseEvent> m_pendingClickEventFromSnapshot;
    133     DeferrableOneShotTimer m_simulatedMouseClickTimer;
     133    ResettableOneShotTimer m_simulatedMouseClickTimer;
    134134    Timer m_removeSnapshotTimer;
    135135    RefPtr<Image> m_snapshotImage;
  • trunk/Source/WebCore/loader/cache/CachedResource.h

    r240014 r240944  
    312312    ResourceResponse m_response;
    313313
    314     DeferrableOneShotTimer m_decodedDataDeletionTimer;
     314    ResettableOneShotTimer m_decodedDataDeletionTimer;
    315315
    316316    // FIXME: Make the rest of these data members private and use functions in derived classes instead.
  • trunk/Source/WebCore/platform/Timer.cpp

    r239814 r240944  
    261261TimerBase::~TimerBase()
    262262{
    263     ASSERT(canAccessThreadLocalDataForThread(m_thread.get()));
     263    assertThreadSafety();
    264264    RELEASE_ASSERT(canAccessThreadLocalDataForThread(m_thread.get()) || shouldSuppressThreadSafetyCheck());
    265265    stop();
     
    274274void TimerBase::start(Seconds nextFireInterval, Seconds repeatInterval)
    275275{
    276     ASSERT(canAccessThreadLocalDataForThread(m_thread.get()));
     276    assertThreadSafety();
    277277
    278278    m_repeatInterval = repeatInterval;
     
    282282void TimerBase::stop()
    283283{
    284     ASSERT(canAccessThreadLocalDataForThread(m_thread.get()));
     284    assertThreadSafety();
    285285
    286286    m_repeatInterval = 0_s;
     
    466466void TimerBase::setNextFireTime(MonotonicTime newTime)
    467467{
    468     ASSERT(canAccessThreadLocalDataForThread(m_thread.get()));
     468    assertThreadSafety();
    469469    RELEASE_ASSERT(canAccessThreadLocalDataForThread(m_thread.get()) || shouldSuppressThreadSafetyCheck());
    470470    RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(!m_wasDeleted);
     
    521521}
    522522
     523DeferrableOneShotTimer::DeferrableOneShotTimer(WTF::Function<void()>&& function)
     524    : m_function(WTFMove(function))
     525{
     526}
     527
     528DeferrableOneShotTimer::~DeferrableOneShotTimer() = default;
     529
     530void DeferrableOneShotTimer::startOneShot(Seconds interval)
     531{
     532    assertThreadSafety();
     533
     534    MonotonicTime oldNextFireTime = TimerBase::nextFireTime();
     535    if (!oldNextFireTime) {
     536        m_restartFireTime = MonotonicTime();
     537        TimerBase::startOneShot(interval);
     538        return;
     539    }
     540
     541    MonotonicTime newNextFireTime = MonotonicTime::now() + interval;
     542    if (newNextFireTime < oldNextFireTime) {
     543        m_restartFireTime = MonotonicTime();
     544        TimerBase::setNextFireTime(newNextFireTime);
     545        return;
     546    }
     547
     548    m_restartFireTime = newNextFireTime;
     549}
     550
     551void DeferrableOneShotTimer::stop()
     552{
     553    TimerBase::stop();
     554}
     555
     556void DeferrableOneShotTimer::fired()
     557{
     558    if (m_restartFireTime) {
     559        MonotonicTime now = MonotonicTime::now();
     560        MonotonicTime restartFireTime = m_restartFireTime;
     561        m_restartFireTime = MonotonicTime();
     562        if (now < restartFireTime) {
     563            TimerBase::setNextFireTime(restartFireTime);
     564            return;
     565        }
     566    }
     567
     568    m_function();
     569}
     570
    523571} // namespace WebCore
    524572
  • trunk/Source/WebCore/platform/Timer.h

    r239814 r240944  
    6969    static void fireTimersInNestedEventLoop();
    7070
     71protected:
     72    MonotonicTime nextFireTime() const { return m_heapItem ? m_heapItem->time : MonotonicTime { }; }
     73    void setNextFireTime(MonotonicTime);
     74
     75    void assertThreadSafety()
     76    {
     77        ASSERT(canAccessThreadLocalDataForThread(m_thread.get()));
     78    }
     79
    7180private:
    7281    virtual void fired() = 0;
     
    7685    void checkConsistency() const;
    7786    void checkHeapIndex() const;
    78 
    79     void setNextFireTime(MonotonicTime);
    8087
    8188    bool inHeap() const { return m_heapItem && m_heapItem->isInHeap(); }
     
    9299    void heapPopMin();
    93100    static void heapDeleteNullMin(ThreadTimerHeap&);
    94 
    95     MonotonicTime nextFireTime() const { return m_heapItem ? m_heapItem->time : MonotonicTime { }; }
    96101
    97102    MonotonicTime m_unalignedNextFireTime; // m_nextFireTime not considering alignment interval
     
    142147}
    143148
    144 class DeferrableOneShotTimer : protected TimerBase {
     149// ResettableOneShotTimer is a optimization for timers that need to be delayed frequently.
     150//
     151// Changing the deadline of a timer is not a cheap operation. When it is done frequently, it can
     152// affect performance.
     153//
     154// With ResettableOneShotTimer, calling restart() does not change the underlying timer.
     155// Instead, when the underlying timer fires, a new dealine is set for "delay" seconds.
     156//
     157// When a ResettableOneShotTimer of 5 seconds is restarted before the deadline, the total
     158// time before the function is called is 10 seconds.
     159//
     160// If a timer is unfrequently reset, or if it is usually stopped before the deadline,
     161// prefer WebCore::Timer to avoid idle wake-up.
     162class ResettableOneShotTimer : protected TimerBase {
    145163    WTF_MAKE_FAST_ALLOCATED;
    146164public:
    147165    template<typename TimerFiredClass>
    148     DeferrableOneShotTimer(TimerFiredClass& object, void (TimerFiredClass::*function)(), Seconds delay)
    149         : DeferrableOneShotTimer(std::bind(function, &object), delay)
    150     {
    151     }
    152 
    153     DeferrableOneShotTimer(WTF::Function<void ()>&& function, Seconds delay)
     166    ResettableOneShotTimer(TimerFiredClass& object, void (TimerFiredClass::*function)(), Seconds delay)
     167        : ResettableOneShotTimer(std::bind(function, &object), delay)
     168    {
     169    }
     170
     171    ResettableOneShotTimer(WTF::Function<void()>&& function, Seconds delay)
    154172        : m_function(WTFMove(function))
    155173        , m_delay(delay)
     
    197215};
    198216
     217// DeferrableOneShotTimer is a optimization for timers that need to change the deadline frequently.
     218//
     219// With DeferrableOneShotTimer, if the new deadline is later than the original deadline, the timer
     220// is not reset. Instead, the timer fires and schedule a new timer for the remaining time.
     221//
     222// DeferrableOneShotTimer supports absolute deadlines.
     223// If a timer of 5 seconds is restarted after 2 seconds, the total time will be 7 seconds.
     224//
     225// Restarting a DeferrableOneShotTimer is more expensive than restarting a ResettableOneShotTimer.
     226// If accumulating the delay is not important, prefer ResettableOneShotTimer.
     227class WEBCORE_EXPORT DeferrableOneShotTimer : private TimerBase {
     228    WTF_MAKE_FAST_ALLOCATED;
     229public:
     230    DeferrableOneShotTimer(WTF::Function<void()>&&);
     231    ~DeferrableOneShotTimer();
     232
     233    void startOneShot(Seconds interval);
     234    void stop();
     235
     236private:
     237    void fired() override;
     238
     239    WTF::Function<void()> m_function;
     240    MonotonicTime m_restartFireTime;
     241};
     242
    199243}
  • trunk/Source/WebCore/platform/graphics/ca/TileController.h

    r239535 r240944  
    208208
    209209    Timer m_tileRevalidationTimer;
    210     DeferrableOneShotTimer m_tileSizeChangeTimer;
     210    ResettableOneShotTimer m_tileSizeChangeTimer;
    211211
    212212    TileCoverage m_tileCoverage { CoverageForVisibleArea };
  • trunk/Source/WebCore/platform/graphics/cg/SubimageCacheWithTimer.h

    r232139 r240944  
    9595    HashCountedSet<CGImageRef> m_images;
    9696    SubimageCacheHashSet m_cache;
    97     DeferrableOneShotTimer m_timer;
     97    ResettableOneShotTimer m_timer;
    9898
    9999    static SubimageCacheWithTimer& subimageCache();
  • trunk/Source/WebKit/ChangeLog

    r240940 r240944  
     12019-02-04  Benjamin Poulain  <benjamin@webkit.org>
     2
     3        Use deferrable timer to restart the Responsiveness Timer on each wheel event
     4        https://bugs.webkit.org/show_bug.cgi?id=194135
     5
     6        Reviewed by Simon Fraser.
     7
     8        Simon Fraser suggested a neat improvement over my previous optimization
     9        of ResponsivenessTimer.
     10
     11        Instead of reseting the deadline with every event, we can let the timer
     12        fire and add the missing time from the last start.
     13
     14        I implemented that behavior in the new Deferrable Timer class and use
     15        it from ResponsivenessTimer.
     16
     17        * NetworkProcess/watchos/NetworkProximityAssertion.h:
     18        * UIProcess/ResponsivenessTimer.h:
     19        * WebProcess/Plugins/PluginView.h:
     20
    1212019-02-04  Simon Fraser  <simon.fraser@apple.com>
    222
  • trunk/Source/WebKit/NetworkProcess/watchos/NetworkProximityAssertion.h

    r234968 r240944  
    8888    uint64_t m_assertionCount { 0 };
    8989    State m_state { State::Suspended };
    90     WebCore::DeferrableOneShotTimer m_releaseTimer;
    91     WebCore::DeferrableOneShotTimer m_suspendAfterBackgroundingTimer;
     90    WebCore::ResettableOneShotTimer m_releaseTimer;
     91    WebCore::ResettableOneShotTimer m_suspendAfterBackgroundingTimer;
    9292};
    9393
  • trunk/Source/WebKit/UIProcess/ResponsivenessTimer.cpp

    r240759 r240944  
    3333ResponsivenessTimer::ResponsivenessTimer(ResponsivenessTimer::Client& client)
    3434    : m_client(client)
    35     , m_timer(*this, &ResponsivenessTimer::timerFired)
     35    , m_timer(std::bind(&ResponsivenessTimer::timerFired, this))
    3636{
    3737}
  • trunk/Source/WebKit/UIProcess/ResponsivenessTimer.h

    r240759 r240944  
    7272
    7373    ResponsivenessTimer::Client& m_client;
    74     WebCore::Timer m_timer;
     74    WebCore::DeferrableOneShotTimer m_timer;
    7575    bool m_isResponsive { true };
    7676    bool m_waitingForTimer { false };
  • trunk/Source/WebKit/WebProcess/Plugins/PluginView.h

    r234920 r240944  
    285285    RefPtr<ShareableBitmap> m_transientPaintingSnapshot;
    286286    // This timer is used when plugin snapshotting is enabled, to capture a plugin placeholder.
    287     WebCore::DeferrableOneShotTimer m_pluginSnapshotTimer;
     287    WebCore::ResettableOneShotTimer m_pluginSnapshotTimer;
    288288#if ENABLE(PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC) || PLATFORM(COCOA)
    289289    unsigned m_countSnapshotRetries { 0 };
Note: See TracChangeset for help on using the changeset viewer.