x11: Reduce chances XPending does recvmsg() syscall

XPending() will do a recvmsg() syscall if there are no items in the queue.
In most cases, this is unnecessary because we know that there is data to be
read of the connection or there are items already read which simply need
to be processed.

Discovering both of those conditions can be done without recvmsg() in the
hot paths.

Before this path, every iteration of the main loop had the potential to
submit a recvmsg() syscall. This reduces that overhead drastically.

XFlush() on the other-hand knows if it needs to write data or not and will
do no IO in the case the buffer is empty.

Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/3653
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/4006>
This commit is contained in:
Christian Hergert 2024-09-05 11:10:12 -07:00 committed by Marge Bot
parent 1247452d19
commit 971bf15f26

View File

@ -33,7 +33,9 @@ meta_x11_event_source_prepare (GSource *source,
*timeout = -1;
return XPending (event_source->xdisplay);
XFlush (event_source->xdisplay);
return XEventsQueued (event_source->xdisplay, QueuedAlready) > 0;
}
static gboolean
@ -41,7 +43,8 @@ meta_x11_event_source_check (GSource *source)
{
MetaX11EventSource *event_source = (MetaX11EventSource *) source;
return XPending (event_source->xdisplay);
return (event_source->event_poll_fd.revents & G_IO_IN) != 0 ||
XEventsQueued (event_source->xdisplay, QueuedAlready) > 0;
}
static gboolean
@ -52,12 +55,16 @@ meta_x11_event_source_dispatch (GSource *source,
MetaX11EventSource *event_source = (MetaX11EventSource *) source;
MetaX11EventFunc event_func = (MetaX11EventFunc) callback;
gboolean retval = G_SOURCE_CONTINUE;
int pending;
while (retval == G_SOURCE_CONTINUE &&
XPending (event_source->xdisplay))
pending = XPending (event_source->xdisplay);
while (retval == G_SOURCE_CONTINUE && pending > 0)
{
XEvent xevent;
pending--;
XNextEvent (event_source->xdisplay, &xevent);
retval = event_func (&xevent, user_data);
}