Title: [270132] trunk
Revision
270132
Author
[email protected]
Date
2020-11-20 14:04:42 -0800 (Fri, 20 Nov 2020)

Log Message

Use a Version 1 CFRunLoopSource for faster task dispatch
https://bugs.webkit.org/show_bug.cgi?id=202874

Reviewed by Simon Fraser.

Source/WTF:

This performance bottleneck showed up in IndexedDB. We worked around it
by switching to WorkQueueMessageReceiver. Now it's showing up again
in the GPU Process.

* wtf/RunLoop.h: Added a mach port. We use this for wake-up.

* wtf/cf/RunLoopCF.cpp:
(WTF::RunLoop::performWork): Use the standard declaration for a
Version 1 run loop source callback.

(WTF::RunLoop::RunLoop): Use a dummy mach port for wake-ups. The default
wake-up mechanism uses pthread APIs, which cost hundreds of microseconds
per invocation, even on the most modern hardware. In contrast, a mach
message takes about nine microseconds.

(WTF::RunLoop::~RunLoop): Free the mach port.

(WTF::RunLoop::wakeUp): Copy-pasted code to signal a mach port. The
message payload doesn't matter because we're just trying to achieve
a wakeup, kind of like calling a void() function.

Tools:

Fixed a test incompatibiilty.

* TestWebKitAPI/cocoa/UtilitiesCocoa.mm:
(TestWebKitAPI::Util::spinRunLoop): Be sure to run the runloop until
it runs out of sources to handle.

The SuspendServiceWorkerProcessBasedOnClientProcesses test invokes
spinRunLoop while adding items to the runloop. Under those conditions,
whether a given source will fire or not in a single invocation of
CFRunLoopRunInMode is undefined behavior.

Modified Paths

Diff

Modified: trunk/Source/WTF/ChangeLog (270131 => 270132)


--- trunk/Source/WTF/ChangeLog	2020-11-20 21:27:12 UTC (rev 270131)
+++ trunk/Source/WTF/ChangeLog	2020-11-20 22:04:42 UTC (rev 270132)
@@ -1,3 +1,31 @@
+2020-11-20  Geoffrey Garen  <[email protected]>
+
+        Use a Version 1 CFRunLoopSource for faster task dispatch
+        https://bugs.webkit.org/show_bug.cgi?id=202874
+
+        Reviewed by Simon Fraser.
+
+        This performance bottleneck showed up in IndexedDB. We worked around it
+        by switching to WorkQueueMessageReceiver. Now it's showing up again
+        in the GPU Process.
+
+        * wtf/RunLoop.h: Added a mach port. We use this for wake-up.
+
+        * wtf/cf/RunLoopCF.cpp:
+        (WTF::RunLoop::performWork): Use the standard declaration for a
+        Version 1 run loop source callback.
+
+        (WTF::RunLoop::RunLoop): Use a dummy mach port for wake-ups. The default
+        wake-up mechanism uses pthread APIs, which cost hundreds of microseconds
+        per invocation, even on the most modern hardware. In contrast, a mach
+        message takes about nine microseconds.
+
+        (WTF::RunLoop::~RunLoop): Free the mach port.
+
+        (WTF::RunLoop::wakeUp): Copy-pasted code to signal a mach port. The
+        message payload doesn't matter because we're just trying to achieve
+        a wakeup, kind of like calling a void() function.
+
 2020-11-20  Don Olmstead  <[email protected]>
 
         Remove quota module

Modified: trunk/Source/WTF/wtf/RunLoop.h (270131 => 270132)


--- trunk/Source/WTF/wtf/RunLoop.h	2020-11-20 21:27:12 UTC (rev 270131)
+++ trunk/Source/WTF/wtf/RunLoop.h	2020-11-20 22:04:42 UTC (rev 270132)
@@ -225,9 +225,10 @@
 
     Lock m_loopLock;
 #elif USE(COCOA_EVENT_LOOP)
-    static void performWork(void*);
+    static void performWork(CFMachPortRef, void* msg, CFIndex size, void* info);
     RetainPtr<CFRunLoopRef> m_runLoop;
     RetainPtr<CFRunLoopSourceRef> m_runLoopSource;
+    RetainPtr<CFMachPortRef> m_port;
 #elif USE(GLIB_EVENT_LOOP)
     void notify(Event, const char*);
 

Modified: trunk/Source/WTF/wtf/cf/RunLoopCF.cpp (270131 => 270132)


--- trunk/Source/WTF/wtf/cf/RunLoopCF.cpp	2020-11-20 21:27:12 UTC (rev 270131)
+++ trunk/Source/WTF/wtf/cf/RunLoopCF.cpp	2020-11-20 22:04:42 UTC (rev 270132)
@@ -28,6 +28,7 @@
 
 #include <CoreFoundation/CoreFoundation.h>
 #include <dispatch/dispatch.h>
+#include <mach/mach.h>
 #include <wtf/AutodrainedPool.h>
 #include <wtf/SchedulePair.h>
 
@@ -40,29 +41,39 @@
     return adoptCF(CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + interval.seconds(), repeatInterval.seconds(), 0, 0, timerFired, &context));
 }
 
-void RunLoop::performWork(void* context)
+void RunLoop::performWork(CFMachPortRef, void*, CFIndex, void* info)
 {
     AutodrainedPool pool;
-    static_cast<RunLoop*>(context)->performWork();
+    static_cast<RunLoop*>(info)->performWork();
 }
 
 RunLoop::RunLoop()
     : m_runLoop(CFRunLoopGetCurrent())
 {
-    CFRunLoopSourceContext context = { 0, this, 0, 0, 0, 0, 0, 0, 0, performWork };
-    m_runLoopSource = adoptCF(CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &context));
+    CFMachPortContext context = { 0, this, nullptr, nullptr, nullptr };
+    m_port = adoptCF(CFMachPortCreate(kCFAllocatorDefault, performWork, &context, nullptr));
+    m_runLoopSource = adoptCF(CFMachPortCreateRunLoopSource(kCFAllocatorDefault, m_port.get(), 0));
     CFRunLoopAddSource(m_runLoop.get(), m_runLoopSource.get(), kCFRunLoopCommonModes);
 }
 
 RunLoop::~RunLoop()
 {
+    CFMachPortInvalidate(m_port.get());
     CFRunLoopSourceInvalidate(m_runLoopSource.get());
 }
 
 void RunLoop::wakeUp()
 {
-    CFRunLoopSourceSignal(m_runLoopSource.get());
-    CFRunLoopWakeUp(m_runLoop.get());
+    mach_msg_header_t header;
+    header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0);
+    header.msgh_size = sizeof(mach_msg_header_t);
+    header.msgh_remote_port = CFMachPortGetPort(m_port.get());
+    header.msgh_local_port = MACH_PORT_NULL;
+    header.msgh_id = 0;
+    mach_msg_return_t result = mach_msg(&header, MACH_SEND_MSG | MACH_SEND_TIMEOUT, header.msgh_size, 0, MACH_PORT_NULL, 0, MACH_PORT_NULL);
+    RELEASE_ASSERT(result == MACH_MSG_SUCCESS || result == MACH_SEND_TIMED_OUT);
+    if (result == MACH_SEND_TIMED_OUT)
+        mach_msg_destroy(&header);
 }
 
 RunLoop::CycleResult RunLoop::cycle(RunLoopMode mode)

Modified: trunk/Tools/ChangeLog (270131 => 270132)


--- trunk/Tools/ChangeLog	2020-11-20 21:27:12 UTC (rev 270131)
+++ trunk/Tools/ChangeLog	2020-11-20 22:04:42 UTC (rev 270132)
@@ -1,3 +1,21 @@
+2020-11-20  Geoffrey Garen  <[email protected]>
+
+        Use a Version 1 CFRunLoopSource for faster task dispatch
+        https://bugs.webkit.org/show_bug.cgi?id=202874
+
+        Reviewed by Simon Fraser.
+
+        Fixed a test incompatibiilty.
+
+        * TestWebKitAPI/cocoa/UtilitiesCocoa.mm:
+        (TestWebKitAPI::Util::spinRunLoop): Be sure to run the runloop until
+        it runs out of sources to handle.
+
+        The SuspendServiceWorkerProcessBasedOnClientProcesses test invokes
+        spinRunLoop while adding items to the runloop. Under those conditions,
+        whether a given source will fire or not in a single invocation of
+        CFRunLoopRunInMode is undefined behavior.
+
 2020-11-20  Don Olmstead  <[email protected]>
 
         Remove quota module

Modified: trunk/Tools/TestWebKitAPI/cocoa/UtilitiesCocoa.mm (270131 => 270132)


--- trunk/Tools/TestWebKitAPI/cocoa/UtilitiesCocoa.mm	2020-11-20 21:27:12 UTC (rev 270131)
+++ trunk/Tools/TestWebKitAPI/cocoa/UtilitiesCocoa.mm	2020-11-20 22:04:42 UTC (rev 270132)
@@ -38,7 +38,7 @@
 void spinRunLoop(uint64_t count)
 {
     for (uint64_t i = 0; i < count; ++i)
-        [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantPast]];
+        while (CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true) == kCFRunLoopRunHandledSource) { }
 }
 
 void sleep(double seconds)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to