Changeset 234384 in webkit


Ignore:
Timestamp:
Jul 30, 2018 2:47:31 PM (6 years ago)
Author:
Wenson Hsieh
Message:

REGRESSION (r230817): Terrible performance when selecting text on Stash code review
https://bugs.webkit.org/show_bug.cgi?id=188144
<rdar://problem/42642489>

Reviewed by Darin Adler.

After r230817, mouse events were serially dispatched to the web process and handled before the subsequent mouse
event. However, this resulted in rapid-fire mouse move events filling up the mouse event queue in the case where
mouse move events were being handled by the web process at a slower rate than the UI process was enqueueing
them. To mitigate this, r231511 introduced a mechanism for replacing the most recently enqueued mouse move event
with an incoming mouse move event.

However, when a user with a force-click-enabled trackpad performs a mouse drag, a rapid stream of
"mouseforcechanged" events is interleaved alongside the stream of "mousemove" events. This renders r231511
ineffective, since the most recently queued event is often a "mouseforcechanged" event instead of a "mousemove".
On the stash code review page, this can result in hundreds of mouse events being backed up in the mouse event
queue, causing perceived slowness when selecting text.

To fix this, we extend the mechanism introduced in r231511, such that it is capable of replacing both
"mouseforcechanged" and "mousemove" events in the queue. Rather than consider only the most recently queued
item, we instead find the most recently queued event that matches the type of the incoming event, remove it from
the queue, and then append the incoming event to the end of the queue. To avoid the risk of removing the only
"mousemove" or "mouseforcechanged" event in the middle of a mouse down and mouse up, we also bail when searching
backwards for an event to replace if we come across any event that is neither of these types.

This effectively throttles the rate at which mouseforcechanged or mousemove events are dispatched when a user
with force-click-enabled hardware clicks and drags the mouse across the page.

  • UIProcess/WebPageProxy.cpp:

(WebKit::removeOldRedundantEvent):
(WebKit::WebPageProxy::handleMouseEvent):

Location:
trunk/Source/WebKit
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit/ChangeLog

    r234382 r234384  
     12018-07-30  Wenson Hsieh  <wenson_hsieh@apple.com>
     2
     3        REGRESSION (r230817): Terrible performance when selecting text on Stash code review
     4        https://bugs.webkit.org/show_bug.cgi?id=188144
     5        <rdar://problem/42642489>
     6
     7        Reviewed by Darin Adler.
     8
     9        After r230817, mouse events were serially dispatched to the web process and handled before the subsequent mouse
     10        event. However, this resulted in rapid-fire mouse move events filling up the mouse event queue in the case where
     11        mouse move events were being handled by the web process at a slower rate than the UI process was enqueueing
     12        them. To mitigate this, r231511 introduced a mechanism for replacing the most recently enqueued mouse move event
     13        with an incoming mouse move event.
     14
     15        However, when a user with a force-click-enabled trackpad performs a mouse drag, a rapid stream of
     16        "mouseforcechanged" events is interleaved alongside the stream of "mousemove" events. This renders r231511
     17        ineffective, since the most recently queued event is often a "mouseforcechanged" event instead of a "mousemove".
     18        On the stash code review page, this can result in hundreds of mouse events being backed up in the mouse event
     19        queue, causing perceived slowness when selecting text.
     20
     21        To fix this, we extend the mechanism introduced in r231511, such that it is capable of replacing both
     22        "mouseforcechanged" and "mousemove" events in the queue. Rather than consider only the most recently queued
     23        item, we instead find the most recently queued event that matches the type of the incoming event, remove it from
     24        the queue, and then append the incoming event to the end of the queue. To avoid the risk of removing the only
     25        "mousemove" or "mouseforcechanged" event in the middle of a mouse down and mouse up, we also bail when searching
     26        backwards for an event to replace if we come across any event that is neither of these types.
     27
     28        This effectively throttles the rate at which mouseforcechanged or mousemove events are dispatched when a user
     29        with force-click-enabled hardware clicks and drags the mouse across the page.
     30
     31        * UIProcess/WebPageProxy.cpp:
     32        (WebKit::removeOldRedundantEvent):
     33        (WebKit::WebPageProxy::handleMouseEvent):
     34
    1352018-07-30  Devin Rousso  <webkit@devinrousso.com>
    236
  • trunk/Source/WebKit/UIProcess/WebPageProxy.cpp

    r234375 r234384  
    19461946#endif // ENABLE(DRAG_SUPPORT)
    19471947
     1948static bool removeOldRedundantEvent(Deque<NativeWebMouseEvent>& queue, WebEvent::Type incomingEventType)
     1949{
     1950    if (incomingEventType != WebEvent::MouseMove && incomingEventType != WebEvent::MouseForceChanged)
     1951        return false;
     1952
     1953    auto it = queue.rbegin();
     1954    auto end = queue.rend();
     1955
     1956    // Must not remove the first event in the deque, since it is already being dispatched.
     1957    if (it != end)
     1958        --end;
     1959
     1960    for (; it != end; ++it) {
     1961        auto type = it->type();
     1962        if (type == incomingEventType) {
     1963            queue.remove(--it.base());
     1964            return true;
     1965        }
     1966        if (type != WebEvent::MouseMove && type != WebEvent::MouseForceChanged)
     1967            break;
     1968    }
     1969    return false;
     1970}
     1971
    19481972void WebPageProxy::handleMouseEvent(const NativeWebMouseEvent& event)
    19491973{
     
    19511975        return;
    19521976
    1953     // If we receive multiple mousemove events and the most recent mousemove event has not been
    1954     // sent to WebProcess for processing, replace the pending mousemove event with a new one.
    1955     if (event.type() == WebEvent::MouseMove && m_mouseEventQueue.size() > 1 && m_mouseEventQueue.last().type() == WebEvent::MouseMove) {
    1956         LOG(MouseHandling, "UIProcess: updated pending mousemove event (queue size %zu)", m_mouseEventQueue.size());
    1957         m_mouseEventQueue.removeLast();
    1958         m_mouseEventQueue.append(event);
    1959     } else {
    1960         LOG(MouseHandling, "UIProcess: enqueued mouse event %s (queue size %zu)", webMouseEventTypeString(event.type()), m_mouseEventQueue.size());
    1961         m_mouseEventQueue.append(event);
    1962     }
     1977    // If we receive multiple mousemove or mouseforcechanged events and the most recent mousemove or mouseforcechanged event
     1978    // (respectively) has not yet been sent to WebProcess for processing, remove the pending mouse event and insert the new
     1979    // event in the queue.
     1980    bool didRemoveEvent = removeOldRedundantEvent(m_mouseEventQueue, event.type());
     1981    m_mouseEventQueue.append(event);
     1982
     1983#if LOG_DISABLED
     1984    UNUSED_PARAM(didRemoveEvent);
     1985#else
     1986    LOG(MouseHandling, "UIProcess: %s mouse event %s (queue size %zu)", didRemoveEvent ? "replaced" : "enqueued", webMouseEventTypeString(event.type()), m_mouseEventQueue.size());
     1987#endif
     1988
    19631989    if (m_mouseEventQueue.size() == 1) // Otherwise, called from DidReceiveEvent message handler.
    19641990        processNextQueuedMouseEvent();
Note: See TracChangeset for help on using the changeset viewer.