Title: [267270] branches/safari-610-branch/Source
Revision
267270
Author
[email protected]
Date
2020-09-18 12:36:17 -0700 (Fri, 18 Sep 2020)

Log Message

Cherry-pick r266677. rdar://problem/68740521

    [MotionMark] RenderLayer::paintLayerContents spends ~5% of the time in MonotonicTime::now() in Multiply
    https://bugs.webkit.org/show_bug.cgi?id=216190

    Reviewed by Darin Adler.

    Source/WebCore:

    In several of MotionMark's subtests (for instance, Multiply), we spent a large amount of time underneath
    `RenderLayer::paintLayerContents` due to both the large number of layers and the need to frequently repaint
    each layer (all of which are constantly being animated). Underneath this method, a nontrivial amount of time
    (~5%) is then spent grabbing the system time via `MonotonicTime::now()`.

    We can avoid this extra work by instead using the timestamp of the last rendering update (before we started
    painting), which we keep track of using a new member variable on `Page`. See below for more details, as well as
    the WebKit2 ChangeLog.

    * page/ChromeClient.h:
    (WebCore::ChromeClient::timestampForPaintFrequencyTracking const):

    Add a client hook to fetch the timestamp to use when tracking painting frequency. See the WebKit2 ChangeLog for
    more details.

    * page/Page.cpp:
    (WebCore::Page::updateRendering):

    Update `m_lastRenderingUpdateTimestamp`.

    * page/Page.h:
    (WebCore::Page::lastRenderingUpdateTimestamp const):
    * rendering/PaintFrequencyTracker.h:

    Drive-by cleanup: narrow the `PaintFrequency` enum to `bool` width.

    (WebCore::PaintFrequencyTracker::begin):
    (WebCore::SinglePaintFrequencyTracking::SinglePaintFrequencyTracking):
    * rendering/RenderLayer.cpp:
    (WebCore::RenderLayer::paintLayerContents):

    Call out to the client layer to return a timestamp for tracking painting frequency. By default, this is simply
    the current time (`MonotonicTime::now()`), but ports (namely, WebKit2) may opt for a coarser granularity.

    (WebCore::RenderLayer::simulateFrequentPaint):
    * rendering/RenderLayer.h:

    Source/WebKit:

    * WebProcess/WebCoreSupport/WebChromeClient.cpp:
    (WebKit::WebChromeClient::timestampForPaintFrequencyTracking const):

    In WebKit2, we can assume (with the exception of SVG pages) that we must've performed a rendering update prior
    to tracking painting frequencies. As such, we can use the page's rendering update timestamp instead of the real
    current time (`MonotonicTime::now()`).

    Note that in WebKit1, it is possible for any client to force a synchronous paint of the page before the page has
    performed a rendering update, which triggers assertions in `SinglePaintFrequencyTracking::end()`. As such, we
    stick with `MonotonicTime::now()` in WebKit1.

    * WebProcess/WebCoreSupport/WebChromeClient.h:

    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@266677 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Modified Paths

Diff

Modified: branches/safari-610-branch/Source/WebCore/ChangeLog (267269 => 267270)


--- branches/safari-610-branch/Source/WebCore/ChangeLog	2020-09-18 19:36:14 UTC (rev 267269)
+++ branches/safari-610-branch/Source/WebCore/ChangeLog	2020-09-18 19:36:17 UTC (rev 267270)
@@ -1,5 +1,115 @@
 2020-09-17  Alan Coon  <[email protected]>
 
+        Cherry-pick r266677. rdar://problem/68740521
+
+    [MotionMark] RenderLayer::paintLayerContents spends ~5% of the time in MonotonicTime::now() in Multiply
+    https://bugs.webkit.org/show_bug.cgi?id=216190
+    
+    Reviewed by Darin Adler.
+    
+    Source/WebCore:
+    
+    In several of MotionMark's subtests (for instance, Multiply), we spent a large amount of time underneath
+    `RenderLayer::paintLayerContents` due to both the large number of layers and the need to frequently repaint
+    each layer (all of which are constantly being animated). Underneath this method, a nontrivial amount of time
+    (~5%) is then spent grabbing the system time via `MonotonicTime::now()`.
+    
+    We can avoid this extra work by instead using the timestamp of the last rendering update (before we started
+    painting), which we keep track of using a new member variable on `Page`. See below for more details, as well as
+    the WebKit2 ChangeLog.
+    
+    * page/ChromeClient.h:
+    (WebCore::ChromeClient::timestampForPaintFrequencyTracking const):
+    
+    Add a client hook to fetch the timestamp to use when tracking painting frequency. See the WebKit2 ChangeLog for
+    more details.
+    
+    * page/Page.cpp:
+    (WebCore::Page::updateRendering):
+    
+    Update `m_lastRenderingUpdateTimestamp`.
+    
+    * page/Page.h:
+    (WebCore::Page::lastRenderingUpdateTimestamp const):
+    * rendering/PaintFrequencyTracker.h:
+    
+    Drive-by cleanup: narrow the `PaintFrequency` enum to `bool` width.
+    
+    (WebCore::PaintFrequencyTracker::begin):
+    (WebCore::SinglePaintFrequencyTracking::SinglePaintFrequencyTracking):
+    * rendering/RenderLayer.cpp:
+    (WebCore::RenderLayer::paintLayerContents):
+    
+    Call out to the client layer to return a timestamp for tracking painting frequency. By default, this is simply
+    the current time (`MonotonicTime::now()`), but ports (namely, WebKit2) may opt for a coarser granularity.
+    
+    (WebCore::RenderLayer::simulateFrequentPaint):
+    * rendering/RenderLayer.h:
+    
+    Source/WebKit:
+    
+    * WebProcess/WebCoreSupport/WebChromeClient.cpp:
+    (WebKit::WebChromeClient::timestampForPaintFrequencyTracking const):
+    
+    In WebKit2, we can assume (with the exception of SVG pages) that we must've performed a rendering update prior
+    to tracking painting frequencies. As such, we can use the page's rendering update timestamp instead of the real
+    current time (`MonotonicTime::now()`).
+    
+    Note that in WebKit1, it is possible for any client to force a synchronous paint of the page before the page has
+    performed a rendering update, which triggers assertions in `SinglePaintFrequencyTracking::end()`. As such, we
+    stick with `MonotonicTime::now()` in WebKit1.
+    
+    * WebProcess/WebCoreSupport/WebChromeClient.h:
+    
+    
+    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@266677 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+    2020-09-05  Wenson Hsieh  <[email protected]>
+
+            [MotionMark] RenderLayer::paintLayerContents spends ~5% of the time in MonotonicTime::now() in Multiply
+            https://bugs.webkit.org/show_bug.cgi?id=216190
+
+            Reviewed by Darin Adler.
+
+            In several of MotionMark's subtests (for instance, Multiply), we spent a large amount of time underneath
+            `RenderLayer::paintLayerContents` due to both the large number of layers and the need to frequently repaint
+            each layer (all of which are constantly being animated). Underneath this method, a nontrivial amount of time
+            (~5%) is then spent grabbing the system time via `MonotonicTime::now()`.
+
+            We can avoid this extra work by instead using the timestamp of the last rendering update (before we started
+            painting), which we keep track of using a new member variable on `Page`. See below for more details, as well as
+            the WebKit2 ChangeLog.
+
+            * page/ChromeClient.h:
+            (WebCore::ChromeClient::timestampForPaintFrequencyTracking const):
+
+            Add a client hook to fetch the timestamp to use when tracking painting frequency. See the WebKit2 ChangeLog for
+            more details.
+
+            * page/Page.cpp:
+            (WebCore::Page::updateRendering):
+
+            Update `m_lastRenderingUpdateTimestamp`.
+
+            * page/Page.h:
+            (WebCore::Page::lastRenderingUpdateTimestamp const):
+            * rendering/PaintFrequencyTracker.h:
+
+            Drive-by cleanup: narrow the `PaintFrequency` enum to `bool` width.
+
+            (WebCore::PaintFrequencyTracker::begin):
+            (WebCore::SinglePaintFrequencyTracking::SinglePaintFrequencyTracking):
+            * rendering/RenderLayer.cpp:
+            (WebCore::RenderLayer::paintLayerContents):
+
+            Call out to the client layer to return a timestamp for tracking painting frequency. By default, this is simply
+            the current time (`MonotonicTime::now()`), but ports (namely, WebKit2) may opt for a coarser granularity.
+
+            (WebCore::RenderLayer::simulateFrequentPaint):
+            * rendering/RenderLayer.h:
+
+2020-09-17  Alan Coon  <[email protected]>
+
         Cherry-pick r266232. rdar://problem/68178664
 
     Step animations invalidate style on every rendering update whether or not they need to

Modified: branches/safari-610-branch/Source/WebCore/page/ChromeClient.h (267269 => 267270)


--- branches/safari-610-branch/Source/WebCore/page/ChromeClient.h	2020-09-18 19:36:14 UTC (rev 267269)
+++ branches/safari-610-branch/Source/WebCore/page/ChromeClient.h	2020-09-18 19:36:17 UTC (rev 267270)
@@ -51,6 +51,7 @@
 #include <wtf/Assertions.h>
 #include <wtf/CompletionHandler.h>
 #include <wtf/Forward.h>
+#include <wtf/MonotonicTime.h>
 #include <wtf/Seconds.h>
 
 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
@@ -455,6 +456,8 @@
 
     virtual bool shouldUseTiledBackingForFrameView(const FrameView&) const { return false; }
 
+    virtual MonotonicTime timestampForPaintFrequencyTracking() const { return MonotonicTime::now(); }
+
     virtual void isPlayingMediaDidChange(MediaProducer::MediaStateFlags, uint64_t) { }
     virtual void handleAutoplayEvent(AutoplayEvent, OptionSet<AutoplayEventFlags>) { }
 

Modified: branches/safari-610-branch/Source/WebCore/page/Page.cpp (267269 => 267270)


--- branches/safari-610-branch/Source/WebCore/page/Page.cpp	2020-09-18 19:36:14 UTC (rev 267269)
+++ branches/safari-610-branch/Source/WebCore/page/Page.cpp	2020-09-18 19:36:17 UTC (rev 267270)
@@ -1437,6 +1437,8 @@
         return;
     }
 
+    m_lastRenderingUpdateTimestamp = MonotonicTime::now();
+
     bool isSVGImagePage = chrome().client().isSVGImageChromeClient();
     if (!isSVGImagePage)
         tracePoint(RenderingUpdateStart);

Modified: branches/safari-610-branch/Source/WebCore/page/Page.h (267269 => 267270)


--- branches/safari-610-branch/Source/WebCore/page/Page.h	2020-09-18 19:36:14 UTC (rev 267269)
+++ branches/safari-610-branch/Source/WebCore/page/Page.h	2020-09-18 19:36:17 UTC (rev 267270)
@@ -779,6 +779,8 @@
     bool hasBeenNotifiedToInjectUserScripts() const { return m_hasBeenNotifiedToInjectUserScripts; }
     WEBCORE_EXPORT void notifyToInjectUserScripts();
 
+    MonotonicTime lastRenderingUpdateTimestamp() const { return m_lastRenderingUpdateTimestamp; }
+
 private:
     struct Navigation {
         RegistrableDomain domain;
@@ -1073,6 +1075,8 @@
     bool m_canUseCredentialStorage { true };
     ShouldRelaxThirdPartyCookieBlocking m_shouldRelaxThirdPartyCookieBlocking { ShouldRelaxThirdPartyCookieBlocking::No };
     bool m_hasBeenNotifiedToInjectUserScripts { false };
+
+    MonotonicTime m_lastRenderingUpdateTimestamp;
 };
 
 inline PageGroup& Page::group()

Modified: branches/safari-610-branch/Source/WebCore/rendering/PaintFrequencyTracker.h (267269 => 267270)


--- branches/safari-610-branch/Source/WebCore/rendering/PaintFrequencyTracker.h	2020-09-18 19:36:14 UTC (rev 267269)
+++ branches/safari-610-branch/Source/WebCore/rendering/PaintFrequencyTracker.h	2020-09-18 19:36:17 UTC (rev 267270)
@@ -37,7 +37,7 @@
 public:
     PaintFrequencyTracker() = default;
 
-    void begin()
+    void begin(MonotonicTime timestamp)
     {
         static unsigned paintFrequencyPaintCountThreshold = 30;
         static Seconds paintFrequencyTimePerFrameThreshold = 32_ms;
@@ -46,14 +46,13 @@
         // Start by assuming the paint frequency is low
         m_paintFrequency = PaintFrequency::Low;
 
-        MonotonicTime now = MonotonicTime::now();
         if (!m_firstPaintTime) {
             // Handle the first time this method is called.
-            m_firstPaintTime = now;
-        } else if (now - m_lastPaintTime > paintFrequencySecondsIdleThreshold) {
+            m_firstPaintTime = timestamp;
+        } else if (timestamp - m_lastPaintTime > paintFrequencySecondsIdleThreshold) {
             // It has been 5 seconds since last time we draw this renderer. Reset the state
             // of this object as if, we've just started tracking the paint frequency.
-            m_firstPaintTime = now;
+            m_firstPaintTime = timestamp;
             m_totalPaints = 0;
         } else if (m_totalPaints >= paintFrequencyPaintCountThreshold && ((m_lastPaintTime - m_firstPaintTime) / m_totalPaints) <= paintFrequencyTimePerFrameThreshold) {
             // Change the paint frequency to be high only if:
@@ -62,7 +61,7 @@
             m_paintFrequency = PaintFrequency::High;
         }
 
-        m_lastPaintTime = now;
+        m_lastPaintTime = timestamp;
         ++m_totalPaints;
     }
 
@@ -79,7 +78,7 @@
     MonotonicTime m_lastPaintTime;
     unsigned m_totalPaints { 0 };
 
-    enum class PaintFrequency { Low, High };
+    enum class PaintFrequency : bool { Low, High };
     PaintFrequency m_paintFrequency { PaintFrequency::Low };
 };
 
@@ -86,12 +85,12 @@
 class SinglePaintFrequencyTracking {
     WTF_MAKE_FAST_ALLOCATED;
 public:
-    SinglePaintFrequencyTracking(PaintFrequencyTracker& paintFrequencyTracker, bool track = true)
+    SinglePaintFrequencyTracking(PaintFrequencyTracker& paintFrequencyTracker, MonotonicTime timestamp, bool track = true)
         : m_paintFrequencyTracker(paintFrequencyTracker)
         , m_track(track)
     {
         if (m_track)
-            m_paintFrequencyTracker.begin();
+            m_paintFrequencyTracker.begin(timestamp);
     }
 
     ~SinglePaintFrequencyTracking()

Modified: branches/safari-610-branch/Source/WebCore/rendering/RenderLayer.cpp (267269 => 267270)


--- branches/safari-610-branch/Source/WebCore/rendering/RenderLayer.cpp	2020-09-18 19:36:14 UTC (rev 267269)
+++ branches/safari-610-branch/Source/WebCore/rendering/RenderLayer.cpp	2020-09-18 19:36:17 UTC (rev 267270)
@@ -4630,7 +4630,7 @@
     bool selectionAndBackgroundsOnly = paintingInfo.paintBehavior.contains(PaintBehavior::SelectionAndBackgroundsOnly);
     bool selectionOnly = paintingInfo.paintBehavior.contains(PaintBehavior::SelectionOnly);
 
-    SinglePaintFrequencyTracking singlePaintFrequencyTracking(m_paintFrequencyTracker, shouldPaintContent);
+    SinglePaintFrequencyTracking singlePaintFrequencyTracking(m_paintFrequencyTracker, page().chrome().client().timestampForPaintFrequencyTracking(), shouldPaintContent && !context.performingPaintInvalidation());
 
     LayerFragments layerFragments;
     RenderObject* subtreePaintRootForRenderer = nullptr;
@@ -7027,6 +7027,11 @@
     return false;
 }
 
+void RenderLayer::simulateFrequentPaint()
+{
+    SinglePaintFrequencyTracking { m_paintFrequencyTracker, page().chrome().client().timestampForPaintFrequencyTracking() };
+}
+
 #if !LOG_DISABLED
 static TextStream& operator<<(TextStream& ts, RenderLayer::EventRegionInvalidationReason reason)
 {

Modified: branches/safari-610-branch/Source/WebCore/rendering/RenderLayer.h (267269 => 267270)


--- branches/safari-610-branch/Source/WebCore/rendering/RenderLayer.h	2020-09-18 19:36:14 UTC (rev 267269)
+++ branches/safari-610-branch/Source/WebCore/rendering/RenderLayer.h	2020-09-18 19:36:17 UTC (rev 267270)
@@ -920,7 +920,7 @@
 
     bool shouldPlaceBlockDirectionScrollbarOnLeft() const final { return renderer().shouldPlaceBlockDirectionScrollbarOnLeft(); }
 
-    void simulateFrequentPaint() { SinglePaintFrequencyTracking { m_paintFrequencyTracker }; }
+    WEBCORE_EXPORT void simulateFrequentPaint();
     bool paintingFrequently() const { return m_paintFrequencyTracker.paintingFrequently(); }
 
     WEBCORE_EXPORT bool isTransparentRespectingParentFrames() const;

Modified: branches/safari-610-branch/Source/WebKit/ChangeLog (267269 => 267270)


--- branches/safari-610-branch/Source/WebKit/ChangeLog	2020-09-18 19:36:14 UTC (rev 267269)
+++ branches/safari-610-branch/Source/WebKit/ChangeLog	2020-09-18 19:36:17 UTC (rev 267270)
@@ -1,5 +1,91 @@
 2020-09-17  Alan Coon  <[email protected]>
 
+        Cherry-pick r266677. rdar://problem/68740521
+
+    [MotionMark] RenderLayer::paintLayerContents spends ~5% of the time in MonotonicTime::now() in Multiply
+    https://bugs.webkit.org/show_bug.cgi?id=216190
+    
+    Reviewed by Darin Adler.
+    
+    Source/WebCore:
+    
+    In several of MotionMark's subtests (for instance, Multiply), we spent a large amount of time underneath
+    `RenderLayer::paintLayerContents` due to both the large number of layers and the need to frequently repaint
+    each layer (all of which are constantly being animated). Underneath this method, a nontrivial amount of time
+    (~5%) is then spent grabbing the system time via `MonotonicTime::now()`.
+    
+    We can avoid this extra work by instead using the timestamp of the last rendering update (before we started
+    painting), which we keep track of using a new member variable on `Page`. See below for more details, as well as
+    the WebKit2 ChangeLog.
+    
+    * page/ChromeClient.h:
+    (WebCore::ChromeClient::timestampForPaintFrequencyTracking const):
+    
+    Add a client hook to fetch the timestamp to use when tracking painting frequency. See the WebKit2 ChangeLog for
+    more details.
+    
+    * page/Page.cpp:
+    (WebCore::Page::updateRendering):
+    
+    Update `m_lastRenderingUpdateTimestamp`.
+    
+    * page/Page.h:
+    (WebCore::Page::lastRenderingUpdateTimestamp const):
+    * rendering/PaintFrequencyTracker.h:
+    
+    Drive-by cleanup: narrow the `PaintFrequency` enum to `bool` width.
+    
+    (WebCore::PaintFrequencyTracker::begin):
+    (WebCore::SinglePaintFrequencyTracking::SinglePaintFrequencyTracking):
+    * rendering/RenderLayer.cpp:
+    (WebCore::RenderLayer::paintLayerContents):
+    
+    Call out to the client layer to return a timestamp for tracking painting frequency. By default, this is simply
+    the current time (`MonotonicTime::now()`), but ports (namely, WebKit2) may opt for a coarser granularity.
+    
+    (WebCore::RenderLayer::simulateFrequentPaint):
+    * rendering/RenderLayer.h:
+    
+    Source/WebKit:
+    
+    * WebProcess/WebCoreSupport/WebChromeClient.cpp:
+    (WebKit::WebChromeClient::timestampForPaintFrequencyTracking const):
+    
+    In WebKit2, we can assume (with the exception of SVG pages) that we must've performed a rendering update prior
+    to tracking painting frequencies. As such, we can use the page's rendering update timestamp instead of the real
+    current time (`MonotonicTime::now()`).
+    
+    Note that in WebKit1, it is possible for any client to force a synchronous paint of the page before the page has
+    performed a rendering update, which triggers assertions in `SinglePaintFrequencyTracking::end()`. As such, we
+    stick with `MonotonicTime::now()` in WebKit1.
+    
+    * WebProcess/WebCoreSupport/WebChromeClient.h:
+    
+    
+    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@266677 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+    2020-09-05  Wenson Hsieh  <[email protected]>
+
+            [MotionMark] RenderLayer::paintLayerContents spends ~5% of the time in MonotonicTime::now() in Multiply
+            https://bugs.webkit.org/show_bug.cgi?id=216190
+
+            Reviewed by Darin Adler.
+
+            * WebProcess/WebCoreSupport/WebChromeClient.cpp:
+            (WebKit::WebChromeClient::timestampForPaintFrequencyTracking const):
+
+            In WebKit2, we can assume (with the exception of SVG pages) that we must've performed a rendering update prior
+            to tracking painting frequencies. As such, we can use the page's rendering update timestamp instead of the real
+            current time (`MonotonicTime::now()`).
+
+            Note that in WebKit1, it is possible for any client to force a synchronous paint of the page before the page has
+            performed a rendering update, which triggers assertions in `SinglePaintFrequencyTracking::end()`. As such, we
+            stick with `MonotonicTime::now()` in WebKit1.
+
+            * WebProcess/WebCoreSupport/WebChromeClient.h:
+
+2020-09-17  Alan Coon  <[email protected]>
+
         Cherry-pick r267031. rdar://problem/69101165
 
     Web Inspector: docking buttons don't work when already docked if window is too small

Modified: branches/safari-610-branch/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp (267269 => 267270)


--- branches/safari-610-branch/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp	2020-09-18 19:36:14 UTC (rev 267269)
+++ branches/safari-610-branch/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp	2020-09-18 19:36:17 UTC (rev 267270)
@@ -1150,6 +1150,11 @@
     return m_page.drawingArea()->shouldUseTiledBackingForFrameView(frameView);
 }
 
+MonotonicTime WebChromeClient::timestampForPaintFrequencyTracking() const
+{
+    return isSVGImageChromeClient() ? MonotonicTime::now() : m_page.corePage()->lastRenderingUpdateTimestamp();
+}
+
 void WebChromeClient::isPlayingMediaDidChange(MediaProducer::MediaStateFlags state, uint64_t sourceElementID)
 {
     m_page.send(Messages::WebPageProxy::IsPlayingMediaDidChange(state, sourceElementID));

Modified: branches/safari-610-branch/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.h (267269 => 267270)


--- branches/safari-610-branch/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.h	2020-09-18 19:36:14 UTC (rev 267269)
+++ branches/safari-610-branch/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.h	2020-09-18 19:36:17 UTC (rev 267270)
@@ -333,6 +333,8 @@
 
     bool shouldUseTiledBackingForFrameView(const WebCore::FrameView&) const final;
 
+    MonotonicTime timestampForPaintFrequencyTracking() const final;
+
     void isPlayingMediaDidChange(WebCore::MediaProducer::MediaStateFlags, uint64_t) final;
     void handleAutoplayEvent(WebCore::AutoplayEvent, OptionSet<WebCore::AutoplayEventFlags>) final;
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to