Title: [241232] trunk/Source/WebKit
Revision
241232
Author
[email protected]
Date
2019-02-08 20:36:57 -0800 (Fri, 08 Feb 2019)

Log Message

[WK2][macOS] Avoid creating new CVDisplayLink objects for each WebProcess
https://bugs.webkit.org/show_bug.cgi?id=194463

Reviewed by Tim Horton.

Avoid creating new CVDisplayLink objects for each WebProcess. We really only need one per
display, creating such object is expensive and it is even worse in a PSON world where we
swap process on navigation.

This patch moves the DisplayLink storing from WebProcessProxy to WebProcessPool. Also,
a DisplayLink can now be associated to several IPC connections instead of having a 1:1
mapping. When a DisplayLink no longer has any observers, we now merely stop it instead
of destroying it.

* UIProcess/Cocoa/WebProcessPoolCocoa.mm:
(WebKit::WebProcessPool::startDisplayLink):
(WebKit::WebProcessPool::stopDisplayLink):
(WebKit::WebProcessPool::stopDisplayLinks):
* UIProcess/WebProcessPool.h:
* UIProcess/WebProcessProxy.cpp:
(WebKit::WebProcessProxy::~WebProcessProxy):
(WebKit::WebProcessProxy::processWillShutDown):
(WebKit::WebProcessProxy::shutDown):
* UIProcess/WebProcessProxy.h:
* UIProcess/mac/DisplayLink.cpp:
(WebKit::DisplayLink::DisplayLink):
(WebKit::DisplayLink::addObserver):
(WebKit::DisplayLink::removeObserver):
(WebKit::DisplayLink::removeObservers):
(WebKit::DisplayLink::hasObservers const):
(WebKit::DisplayLink::displayLinkCallback):
* UIProcess/mac/DisplayLink.h:
* UIProcess/mac/WebProcessProxyMac.mm:
(WebKit::WebProcessProxy::startDisplayLink):
(WebKit::WebProcessProxy::stopDisplayLink):

Modified Paths

Diff

Modified: trunk/Source/WebKit/ChangeLog (241231 => 241232)


--- trunk/Source/WebKit/ChangeLog	2019-02-09 04:06:34 UTC (rev 241231)
+++ trunk/Source/WebKit/ChangeLog	2019-02-09 04:36:57 UTC (rev 241232)
@@ -1,3 +1,41 @@
+2019-02-08  Chris Dumez  <[email protected]>
+
+        [WK2][macOS] Avoid creating new CVDisplayLink objects for each WebProcess
+        https://bugs.webkit.org/show_bug.cgi?id=194463
+
+        Reviewed by Tim Horton.
+
+        Avoid creating new CVDisplayLink objects for each WebProcess. We really only need one per
+        display, creating such object is expensive and it is even worse in a PSON world where we
+        swap process on navigation.
+
+        This patch moves the DisplayLink storing from WebProcessProxy to WebProcessPool. Also,
+        a DisplayLink can now be associated to several IPC connections instead of having a 1:1
+        mapping. When a DisplayLink no longer has any observers, we now merely stop it instead
+        of destroying it.
+
+        * UIProcess/Cocoa/WebProcessPoolCocoa.mm:
+        (WebKit::WebProcessPool::startDisplayLink):
+        (WebKit::WebProcessPool::stopDisplayLink):
+        (WebKit::WebProcessPool::stopDisplayLinks):
+        * UIProcess/WebProcessPool.h:
+        * UIProcess/WebProcessProxy.cpp:
+        (WebKit::WebProcessProxy::~WebProcessProxy):
+        (WebKit::WebProcessProxy::processWillShutDown):
+        (WebKit::WebProcessProxy::shutDown):
+        * UIProcess/WebProcessProxy.h:
+        * UIProcess/mac/DisplayLink.cpp:
+        (WebKit::DisplayLink::DisplayLink):
+        (WebKit::DisplayLink::addObserver):
+        (WebKit::DisplayLink::removeObserver):
+        (WebKit::DisplayLink::removeObservers):
+        (WebKit::DisplayLink::hasObservers const):
+        (WebKit::DisplayLink::displayLinkCallback):
+        * UIProcess/mac/DisplayLink.h:
+        * UIProcess/mac/WebProcessProxyMac.mm:
+        (WebKit::WebProcessProxy::startDisplayLink):
+        (WebKit::WebProcessProxy::stopDisplayLink):
+
 2019-02-08  Alexander Mikhaylenko  <[email protected]>
 
         [GTK] Implement back/forward touchpad gesture

Modified: trunk/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm (241231 => 241232)


--- trunk/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm	2019-02-09 04:06:34 UTC (rev 241231)
+++ trunk/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm	2019-02-09 04:36:57 UTC (rev 241232)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010-2018 Apple Inc. All rights reserved.
+ * Copyright (C) 2010-2019 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -468,6 +468,37 @@
     _CFNetworkResetHSTSHostsSinceDate(privateBrowsingSession(), (__bridge CFDateRef)startDate);
 }
 
+#if PLATFORM(MAC) && ENABLE(WEBPROCESS_WINDOWSERVER_BLOCKING)
+void WebProcessPool::startDisplayLink(IPC::Connection& connection, unsigned observerID, uint32_t displayID)
+{
+    for (auto& displayLink : m_displayLinks) {
+        if (displayLink->displayID() == displayID) {
+            displayLink->addObserver(connection, observerID);
+            return;
+        }
+    }
+    auto displayLink = std::make_unique<DisplayLink>(displayID);
+    displayLink->addObserver(connection, observerID);
+    m_displayLinks.append(WTFMove(displayLink));
+}
+
+void WebProcessPool::stopDisplayLink(IPC::Connection& connection, unsigned observerID, uint32_t displayID)
+{
+    for (auto& displayLink : m_displayLinks) {
+        if (displayLink->displayID() == displayID) {
+            displayLink->removeObserver(connection, observerID);
+            return;
+        }
+    }
+}
+
+void WebProcessPool::stopDisplayLinks(IPC::Connection& connection)
+{
+    for (auto& displayLink : m_displayLinks)
+        displayLink->removeObservers(connection);
+}
+#endif
+
 // FIXME: Deprecated. Left here until a final decision is made.
 void WebProcessPool::setCookieStoragePartitioningEnabled(bool enabled)
 {

Modified: trunk/Source/WebKit/UIProcess/WebProcessPool.h (241231 => 241232)


--- trunk/Source/WebKit/UIProcess/WebProcessPool.h	2019-02-09 04:06:34 UTC (rev 241231)
+++ trunk/Source/WebKit/UIProcess/WebProcessPool.h	2019-02-09 04:36:57 UTC (rev 241232)
@@ -71,6 +71,10 @@
 OBJC_CLASS NSString;
 #endif
 
+#if PLATFORM(MAC) && ENABLE(WEBPROCESS_WINDOWSERVER_BLOCKING)
+#include "DisplayLink.h"
+#endif
+
 namespace API {
 class AutomationClient;
 class CustomProtocolManagerClient;
@@ -208,6 +212,12 @@
     const HashMap<String, HashMap<String, HashMap<String, uint8_t>>>& pluginLoadClientPolicies() const { return m_pluginLoadClientPolicies; }
 #endif
 
+#if PLATFORM(MAC) && ENABLE(WEBPROCESS_WINDOWSERVER_BLOCKING)
+    void startDisplayLink(IPC::Connection&, unsigned observerID, uint32_t displayID);
+    void stopDisplayLink(IPC::Connection&, unsigned observerID, uint32_t displayID);
+    void stopDisplayLinks(IPC::Connection&);
+#endif
+
     void addSupportedPlugin(String&& matchingDomain, String&& name, HashSet<String>&& mimeTypes, HashSet<String> extensions);
     void clearSupportedPlugins();
 
@@ -730,6 +740,10 @@
 
     HashMap<String, std::unique_ptr<WebCore::PrewarmInformation>> m_prewarmInformationPerRegistrableDomain;
 
+#if PLATFORM(MAC) && ENABLE(WEBPROCESS_WINDOWSERVER_BLOCKING)
+    Vector<std::unique_ptr<DisplayLink>> m_displayLinks;
+#endif
+
 #if PLATFORM(GTK) || PLATFORM(WPE)
     bool m_sandboxEnabled { false };
     HashMap<CString, SandboxPermission> m_extraSandboxPaths;

Modified: trunk/Source/WebKit/UIProcess/WebProcessProxy.cpp (241231 => 241232)


--- trunk/Source/WebKit/UIProcess/WebProcessProxy.cpp	2019-02-09 04:06:34 UTC (rev 241231)
+++ trunk/Source/WebKit/UIProcess/WebProcessProxy.cpp	2019-02-09 04:36:57 UTC (rev 241232)
@@ -162,6 +162,11 @@
 
     WebPasteboardProxy::singleton().removeWebProcessProxy(*this);
 
+#if PLATFORM(MAC) && ENABLE(WEBPROCESS_WINDOWSERVER_BLOCKING)
+    if (state() == State::Running)
+        processPool().stopDisplayLinks(*connection());
+#endif
+
     if (m_webConnection)
         m_webConnection->invalidate();
 
@@ -240,6 +245,10 @@
 {
     ASSERT_UNUSED(connection, this->connection() == &connection);
 
+#if PLATFORM(MAC) && ENABLE(WEBPROCESS_WINDOWSERVER_BLOCKING)
+    processPool().stopDisplayLinks(connection);
+#endif
+
     for (auto& page : m_pageMap.values())
         page->webProcessWillShutDown();
 }

Modified: trunk/Source/WebKit/UIProcess/WebProcessProxy.h (241231 => 241232)


--- trunk/Source/WebKit/UIProcess/WebProcessProxy.h	2019-02-09 04:06:34 UTC (rev 241231)
+++ trunk/Source/WebKit/UIProcess/WebProcessProxy.h	2019-02-09 04:36:57 UTC (rev 241232)
@@ -50,10 +50,6 @@
 #include <wtf/RefCounted.h>
 #include <wtf/RefPtr.h>
 
-#if PLATFORM(MAC) && ENABLE(WEBPROCESS_WINDOWSERVER_BLOCKING)
-#include "DisplayLink.h"
-#endif
-
 namespace API {
 class Navigation;
 class PageConfiguration;
@@ -421,10 +417,6 @@
 #if PLATFORM(WATCHOS)
     ProcessThrottler::BackgroundActivityToken m_backgroundActivityTokenForFullscreenFormControls;
 #endif
-
-#if PLATFORM(MAC) && ENABLE(WEBPROCESS_WINDOWSERVER_BLOCKING)
-    Vector<std::unique_ptr<DisplayLink>> m_displayLinks;
-#endif
 };
 
 } // namespace WebKit

Modified: trunk/Source/WebKit/UIProcess/mac/DisplayLink.cpp (241231 => 241232)


--- trunk/Source/WebKit/UIProcess/mac/DisplayLink.cpp	2019-02-09 04:06:34 UTC (rev 241231)
+++ trunk/Source/WebKit/UIProcess/mac/DisplayLink.cpp	2019-02-09 04:36:57 UTC (rev 241232)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 Apple Inc. All rights reserved.
+ * Copyright (C) 2018-2019 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -28,16 +28,13 @@
 
 #if ENABLE(WEBPROCESS_WINDOWSERVER_BLOCKING)
 
-#include "DrawingAreaMessages.h"
 #include "WebProcessMessages.h"
-#include "WebProcessProxy.h"
 #include <wtf/ProcessPrivilege.h>
 
 namespace WebKit {
     
-DisplayLink::DisplayLink(WebCore::PlatformDisplayID displayID, WebProcessProxy& webProcessProxy)
-    : m_connection(webProcessProxy.connection())
-    , m_displayID(displayID)
+DisplayLink::DisplayLink(WebCore::PlatformDisplayID displayID)
+    : m_displayID(displayID)
 {
     ASSERT(hasProcessPrivilege(ProcessPrivilege::CanCommunicateWithWindowServer));
     CVReturn error = CVDisplayLinkCreateWithCGDisplay(displayID, &m_displayLink);
@@ -51,10 +48,6 @@
         WTFLogAlways("Could not set the display link output callback: %d", error);
         return;
     }
-
-    error = CVDisplayLinkStart(m_displayLink);
-    if (error)
-        WTFLogAlways("Could not start the display link: %d", error);
 }
 
 DisplayLink::~DisplayLink()
@@ -68,28 +61,73 @@
     CVDisplayLinkRelease(m_displayLink);
 }
 
-void DisplayLink::addObserver(unsigned observerID)
+void DisplayLink::addObserver(IPC::Connection& connection, unsigned observerID)
 {
-    m_observers.add(observerID);
+    ASSERT(RunLoop::isMain());
+    bool isRunning = !m_observers.isEmpty();
+
+    {
+        LockHolder locker(m_observersLock);
+        m_observers.ensure(&connection, [] {
+            return Vector<unsigned> { };
+        }).iterator->value.append(observerID);
+    }
+
+    if (!isRunning) {
+        CVReturn error = CVDisplayLinkStart(m_displayLink);
+        if (error)
+            WTFLogAlways("Could not start the display link: %d", error);
+    }
 }
 
-void DisplayLink::removeObserver(unsigned observerID)
+void DisplayLink::removeObserver(IPC::Connection& connection, unsigned observerID)
 {
-    m_observers.remove(observerID);
+    ASSERT(RunLoop::isMain());
+
+    {
+        LockHolder locker(m_observersLock);
+
+        auto it = m_observers.find(&connection);
+        if (it == m_observers.end())
+            return;
+        bool removed = it->value.removeFirst(observerID);
+        ASSERT_UNUSED(removed, removed);
+        if (it->value.isEmpty())
+            m_observers.remove(it);
+    }
+
+    if (m_observers.isEmpty())
+        CVDisplayLinkStop(m_displayLink);
 }
 
+void DisplayLink::removeObservers(IPC::Connection& connection)
+{
+    ASSERT(RunLoop::isMain());
+
+    {
+        LockHolder locker(m_observersLock);
+        m_observers.remove(&connection);
+    }
+
+    if (m_observers.isEmpty())
+        CVDisplayLinkStop(m_displayLink);
+}
+
 bool DisplayLink::hasObservers() const
 {
+    ASSERT(RunLoop::isMain());
     return !m_observers.isEmpty();
 }
 
 CVReturn DisplayLink::displayLinkCallback(CVDisplayLinkRef displayLinkRef, const CVTimeStamp*, const CVTimeStamp*, CVOptionFlags, CVOptionFlags*, void* data)
 {
-    DisplayLink* displayLink = static_cast<DisplayLink*>(data);
-    displayLink->m_connection->send(Messages::WebProcess::DisplayWasRefreshed(displayLink->m_displayID), 0);
+    auto* displayLink = static_cast<DisplayLink*>(data);
+    LockHolder locker(displayLink->m_observersLock);
+    for (auto& connection : displayLink->m_observers.keys())
+        connection->send(Messages::WebProcess::DisplayWasRefreshed(displayLink->m_displayID), 0);
     return kCVReturnSuccess;
 }
 
-}
+} // namespace WebKit
 
 #endif

Modified: trunk/Source/WebKit/UIProcess/mac/DisplayLink.h (241231 => 241232)


--- trunk/Source/WebKit/UIProcess/mac/DisplayLink.h	2019-02-09 04:06:34 UTC (rev 241231)
+++ trunk/Source/WebKit/UIProcess/mac/DisplayLink.h	2019-02-09 04:36:57 UTC (rev 241232)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 Apple Inc. All rights reserved.
+ * Copyright (C) 2018-2019 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -28,9 +28,9 @@
 #if ENABLE(WEBPROCESS_WINDOWSERVER_BLOCKING)
 
 #include <CoreVideo/CVDisplayLink.h>
-
 #include <WebCore/PlatformScreen.h>
-#include <wtf/HashSet.h>
+#include <wtf/HashMap.h>
+#include <wtf/Lock.h>
 
 namespace IPC {
 class Connection;
@@ -37,17 +37,16 @@
 }
 
 namespace WebKit {
-
-class WebProcessProxy;
     
 class DisplayLink {
     WTF_MAKE_FAST_ALLOCATED;
 public:
-    DisplayLink(WebCore::PlatformDisplayID, WebProcessProxy&);
+    explicit DisplayLink(WebCore::PlatformDisplayID);
     ~DisplayLink();
     
-    void addObserver(unsigned observerID);
-    void removeObserver(unsigned observerID);
+    void addObserver(IPC::Connection&, unsigned observerID);
+    void removeObserver(IPC::Connection&, unsigned observerID);
+    void removeObservers(IPC::Connection&);
     bool hasObservers() const;
 
     WebCore::PlatformDisplayID displayID() const { return m_displayID; }
@@ -56,12 +55,12 @@
     static CVReturn displayLinkCallback(CVDisplayLinkRef, const CVTimeStamp*, const CVTimeStamp*, CVOptionFlags, CVOptionFlags*, void* data);
     
     CVDisplayLinkRef m_displayLink { nullptr };
-    HashSet<unsigned> m_observers;
-    RefPtr<IPC::Connection> m_connection;
-    WebCore::PlatformDisplayID m_displayID { 0 };
+    Lock m_observersLock;
+    HashMap<RefPtr<IPC::Connection>, Vector<unsigned>> m_observers;
+    WebCore::PlatformDisplayID m_displayID;
 };
 
-}
+} // namespace WebKit
 
 #endif
 

Modified: trunk/Source/WebKit/UIProcess/mac/WebProcessProxyMac.mm (241231 => 241232)


--- trunk/Source/WebKit/UIProcess/mac/WebProcessProxyMac.mm	2019-02-09 04:06:34 UTC (rev 241231)
+++ trunk/Source/WebKit/UIProcess/mac/WebProcessProxyMac.mm	2019-02-09 04:36:57 UTC (rev 241232)
@@ -74,29 +74,14 @@
 void WebProcessProxy::startDisplayLink(unsigned observerID, uint32_t displayID)
 {
     ASSERT(hasProcessPrivilege(ProcessPrivilege::CanCommunicateWithWindowServer));
-    for (auto& displayLink : m_displayLinks) {
-        if (displayLink->displayID() == displayID) {
-            displayLink->addObserver(observerID);
-            return;
-        }
-    }
-    auto displayLink = std::make_unique<DisplayLink>(displayID, *this);
-    displayLink->addObserver(observerID);
-    m_displayLinks.append(WTFMove(displayLink));
+    ASSERT(connection());
+    processPool().startDisplayLink(*connection(), observerID, displayID);
 }
 
 void WebProcessProxy::stopDisplayLink(unsigned observerID, uint32_t displayID)
 {
-    size_t pos = 0;
-    for (auto& displayLink : m_displayLinks) {
-        if (displayLink->displayID() == displayID) {
-            displayLink->removeObserver(observerID);
-            if (!displayLink->hasObservers())
-                m_displayLinks.remove(pos);
-            return;
-        }
-        pos++;
-    }
+    ASSERT(connection());
+    processPool().stopDisplayLink(*connection(), observerID, displayID);
 }
 #endif
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to