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)