Changeset 270132 in webkit


Ignore:
Timestamp:
Nov 20, 2020 2:04:42 PM (3 years ago)
Author:
ggaren@apple.com
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.

Location:
trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WTF/ChangeLog

    r270120 r270132  
     12020-11-20  Geoffrey Garen  <ggaren@apple.com>
     2
     3        Use a Version 1 CFRunLoopSource for faster task dispatch
     4        https://bugs.webkit.org/show_bug.cgi?id=202874
     5
     6        Reviewed by Simon Fraser.
     7
     8        This performance bottleneck showed up in IndexedDB. We worked around it
     9        by switching to WorkQueueMessageReceiver. Now it's showing up again
     10        in the GPU Process.
     11
     12        * wtf/RunLoop.h: Added a mach port. We use this for wake-up.
     13
     14        * wtf/cf/RunLoopCF.cpp:
     15        (WTF::RunLoop::performWork): Use the standard declaration for a
     16        Version 1 run loop source callback.
     17
     18        (WTF::RunLoop::RunLoop): Use a dummy mach port for wake-ups. The default
     19        wake-up mechanism uses pthread APIs, which cost hundreds of microseconds
     20        per invocation, even on the most modern hardware. In contrast, a mach
     21        message takes about nine microseconds.
     22
     23        (WTF::RunLoop::~RunLoop): Free the mach port.
     24
     25        (WTF::RunLoop::wakeUp): Copy-pasted code to signal a mach port. The
     26        message payload doesn't matter because we're just trying to achieve
     27        a wakeup, kind of like calling a void() function.
     28
    1292020-11-20  Don Olmstead  <don.olmstead@sony.com>
    230
  • trunk/Source/WTF/wtf/RunLoop.h

    r269814 r270132  
    226226    Lock m_loopLock;
    227227#elif USE(COCOA_EVENT_LOOP)
    228     static void performWork(void*);
     228    static void performWork(CFMachPortRef, void* msg, CFIndex size, void* info);
    229229    RetainPtr<CFRunLoopRef> m_runLoop;
    230230    RetainPtr<CFRunLoopSourceRef> m_runLoopSource;
     231    RetainPtr<CFMachPortRef> m_port;
    231232#elif USE(GLIB_EVENT_LOOP)
    232233    void notify(Event, const char*);
  • trunk/Source/WTF/wtf/cf/RunLoopCF.cpp

    r264993 r270132  
    2929#include <CoreFoundation/CoreFoundation.h>
    3030#include <dispatch/dispatch.h>
     31#include <mach/mach.h>
    3132#include <wtf/AutodrainedPool.h>
    3233#include <wtf/SchedulePair.h>
     
    4142}
    4243
    43 void RunLoop::performWork(void* context)
     44void RunLoop::performWork(CFMachPortRef, void*, CFIndex, void* info)
    4445{
    4546    AutodrainedPool pool;
    46     static_cast<RunLoop*>(context)->performWork();
     47    static_cast<RunLoop*>(info)->performWork();
    4748}
    4849
     
    5051    : m_runLoop(CFRunLoopGetCurrent())
    5152{
    52     CFRunLoopSourceContext context = { 0, this, 0, 0, 0, 0, 0, 0, 0, performWork };
    53     m_runLoopSource = adoptCF(CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &context));
     53    CFMachPortContext context = { 0, this, nullptr, nullptr, nullptr };
     54    m_port = adoptCF(CFMachPortCreate(kCFAllocatorDefault, performWork, &context, nullptr));
     55    m_runLoopSource = adoptCF(CFMachPortCreateRunLoopSource(kCFAllocatorDefault, m_port.get(), 0));
    5456    CFRunLoopAddSource(m_runLoop.get(), m_runLoopSource.get(), kCFRunLoopCommonModes);
    5557}
     
    5759RunLoop::~RunLoop()
    5860{
     61    CFMachPortInvalidate(m_port.get());
    5962    CFRunLoopSourceInvalidate(m_runLoopSource.get());
    6063}
     
    6265void RunLoop::wakeUp()
    6366{
    64     CFRunLoopSourceSignal(m_runLoopSource.get());
    65     CFRunLoopWakeUp(m_runLoop.get());
     67    mach_msg_header_t header;
     68    header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0);
     69    header.msgh_size = sizeof(mach_msg_header_t);
     70    header.msgh_remote_port = CFMachPortGetPort(m_port.get());
     71    header.msgh_local_port = MACH_PORT_NULL;
     72    header.msgh_id = 0;
     73    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);
     74    RELEASE_ASSERT(result == MACH_MSG_SUCCESS || result == MACH_SEND_TIMED_OUT);
     75    if (result == MACH_SEND_TIMED_OUT)
     76        mach_msg_destroy(&header);
    6677}
    6778
  • trunk/Tools/ChangeLog

    r270120 r270132  
     12020-11-20  Geoffrey Garen  <ggaren@apple.com>
     2
     3        Use a Version 1 CFRunLoopSource for faster task dispatch
     4        https://bugs.webkit.org/show_bug.cgi?id=202874
     5
     6        Reviewed by Simon Fraser.
     7
     8        Fixed a test incompatibiilty.
     9
     10        * TestWebKitAPI/cocoa/UtilitiesCocoa.mm:
     11        (TestWebKitAPI::Util::spinRunLoop): Be sure to run the runloop until
     12        it runs out of sources to handle.
     13
     14        The SuspendServiceWorkerProcessBasedOnClientProcesses test invokes
     15        spinRunLoop while adding items to the runloop. Under those conditions,
     16        whether a given source will fire or not in a single invocation of
     17        CFRunLoopRunInMode is undefined behavior.
     18
    1192020-11-20  Don Olmstead  <don.olmstead@sony.com>
    220
  • trunk/Tools/TestWebKitAPI/cocoa/UtilitiesCocoa.mm

    r260366 r270132  
    3939{
    4040    for (uint64_t i = 0; i < count; ++i)
    41         [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantPast]];
     41        while (CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true) == kCFRunLoopRunHandledSource) { }
    4242}
    4343
Note: See TracChangeset for help on using the changeset viewer.