XWayland: Don't dispatch xwayland events in QAbstractEventDispatcher sleeps
QAbstractEventDispatcher blocks and waits constantly on every external event processed; every timer or update from an X or wayland client, mouse move or DRM event. Right now every time this happens we go and check Xwayland for new events, this is a system call (poll) that based on strace will unsurprisingly immediately return with EAGAIN as there's nothing to read from X. If there is something to read our socket notifier will fire. On block we do still need to read any events read in the meantime that weren't dispatched. This cuts down our system calls significantly, which hopefully should have a noticeable impact on performance especially when the kernel is under load. --- Found whilst analysing strace (by accident whilst looking for something else!) In a simple case of xwayland nested running glxgears we go from 28 calls per frame to 21. With many many clients and more input events it'll be an even higher percentage.
This commit is contained in:
parent
d983b78107
commit
fbb71f9c0b
2 changed files with 21 additions and 8 deletions
|
@ -224,7 +224,7 @@ XwaylandLauncher *Xwayland::xwaylandLauncher() const
|
|||
return m_launcher;
|
||||
}
|
||||
|
||||
void Xwayland::dispatchEvents()
|
||||
void Xwayland::dispatchEvents(DispatchEventsMode mode)
|
||||
{
|
||||
xcb_connection_t *connection = kwinApp()->x11Connection();
|
||||
if (!connection) {
|
||||
|
@ -239,12 +239,15 @@ void Xwayland::dispatchEvents()
|
|||
return;
|
||||
}
|
||||
|
||||
while (xcb_generic_event_t *event = xcb_poll_for_event(connection)) {
|
||||
auto pollEventFunc = mode == DispatchEventsMode::Poll ? xcb_poll_for_event : xcb_poll_for_queued_event;
|
||||
|
||||
while (xcb_generic_event_t *event = pollEventFunc(connection)) {
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
||||
long result = 0;
|
||||
#else
|
||||
qintptr result = 0;
|
||||
#endif
|
||||
|
||||
QAbstractEventDispatcher *dispatcher = QCoreApplication::eventDispatcher();
|
||||
dispatcher->filterNativeEvent(QByteArrayLiteral("xcb_generic_event_t"), event, &result);
|
||||
free(event);
|
||||
|
@ -258,18 +261,23 @@ void Xwayland::installSocketNotifier()
|
|||
const int fileDescriptor = xcb_get_file_descriptor(kwinApp()->x11Connection());
|
||||
|
||||
m_socketNotifier = new QSocketNotifier(fileDescriptor, QSocketNotifier::Read, this);
|
||||
connect(m_socketNotifier, &QSocketNotifier::activated, this, &Xwayland::dispatchEvents);
|
||||
connect(m_socketNotifier, &QSocketNotifier::activated, this, [this]() {
|
||||
dispatchEvents(DispatchEventsMode::Poll);
|
||||
});
|
||||
|
||||
QAbstractEventDispatcher *dispatcher = QCoreApplication::eventDispatcher();
|
||||
connect(dispatcher, &QAbstractEventDispatcher::aboutToBlock, this, &Xwayland::dispatchEvents);
|
||||
connect(dispatcher, &QAbstractEventDispatcher::awake, this, &Xwayland::dispatchEvents);
|
||||
connect(dispatcher, &QAbstractEventDispatcher::aboutToBlock, this, [this]() {
|
||||
dispatchEvents(DispatchEventsMode::EventQueue);
|
||||
});
|
||||
connect(dispatcher, &QAbstractEventDispatcher::awake, this, [this]() {
|
||||
dispatchEvents(DispatchEventsMode::EventQueue);
|
||||
});
|
||||
}
|
||||
|
||||
void Xwayland::uninstallSocketNotifier()
|
||||
{
|
||||
QAbstractEventDispatcher *dispatcher = QCoreApplication::eventDispatcher();
|
||||
disconnect(dispatcher, &QAbstractEventDispatcher::aboutToBlock, this, &Xwayland::dispatchEvents);
|
||||
disconnect(dispatcher, &QAbstractEventDispatcher::awake, this, &Xwayland::dispatchEvents);
|
||||
disconnect(dispatcher, nullptr, this, nullptr);
|
||||
|
||||
delete m_socketNotifier;
|
||||
m_socketNotifier = nullptr;
|
||||
|
|
|
@ -57,7 +57,6 @@ Q_SIGNALS:
|
|||
private Q_SLOTS:
|
||||
void handleXwaylandFinished();
|
||||
void handleXwaylandReady();
|
||||
void dispatchEvents();
|
||||
|
||||
void handleSelectionLostOwnership();
|
||||
void handleSelectionFailedToClaimOwnership();
|
||||
|
@ -66,6 +65,12 @@ private Q_SLOTS:
|
|||
private:
|
||||
friend class XrandrEventFilter;
|
||||
|
||||
enum class DispatchEventsMode {
|
||||
Poll,
|
||||
EventQueue
|
||||
};
|
||||
void dispatchEvents(DispatchEventsMode mode);
|
||||
|
||||
void installSocketNotifier();
|
||||
void uninstallSocketNotifier();
|
||||
void updatePrimary();
|
||||
|
|
Loading…
Reference in a new issue