From 3e6b42ae9dbf4f90ba890d78a4c49f9936f4976b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A5rten=20Nordheim?= Date: Fri, 27 Aug 2021 16:48:21 +0200 Subject: [PATCH] compressEvents: limit iteration Slightly improves performance in the new benchmark Change-Id: I2d71143ff7bc1f32ebb172f20be1843dec123e6c Reviewed-by: Allan Sandfeld Jensen --- src/corelib/kernel/qcoreapplication.cpp | 18 ++++++++----- .../tst_bench_qcoreapplication.cpp | 26 +++++++++++++++++++ 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 88f855a89e6..60f956faed4 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -1729,15 +1729,21 @@ bool QCoreApplication::compressEvent(QEvent *event, QObject *receiver, QPostEven Q_ASSERT(receiver); Q_ASSERT(postedEvents); + auto receiverPostedEvents = receiver->d_func()->postedEvents; // compress posted timers to this object. - if (event->type() == QEvent::Timer && receiver->d_func()->postedEvents > 0) { - int timerId = ((QTimerEvent *) event)->timerId(); - for (const QPostEvent &e : std::as_const(*postedEvents)) { - if (e.receiver == receiver && e.event && e.event->type() == QEvent::Timer - && ((QTimerEvent *) e.event)->timerId() == timerId) { + if (event->type() == QEvent::Timer && receiverPostedEvents > 0) { + int timerId = static_cast(event)->timerId(); + auto sameReceiver = [receiver](const QPostEvent &e) { return e.receiver == receiver; }; + auto it = std::find_if(postedEvents->cbegin(), postedEvents->cend(), sameReceiver); + while (receiverPostedEvents > 0 && it != postedEvents->cend()) { + if (it->event && it->event->type() == QEvent::Timer + && static_cast(it->event)->timerId() == timerId) { delete event; return true; } + + if (--receiverPostedEvents) + it = std::find_if(it + 1, postedEvents->cend(), sameReceiver); } return false; } @@ -1753,7 +1759,7 @@ bool QCoreApplication::compressEvent(QEvent *event, QObject *receiver, QPostEven return false; } - if (event->type() == QEvent::Quit && receiver->d_func()->postedEvents > 0) { + if (event->type() == QEvent::Quit && receiverPostedEvents > 0) { for (const QPostEvent &cur : std::as_const(*postedEvents)) { if (cur.receiver != receiver || cur.event == nullptr diff --git a/tests/benchmarks/corelib/kernel/qcoreapplication/tst_bench_qcoreapplication.cpp b/tests/benchmarks/corelib/kernel/qcoreapplication/tst_bench_qcoreapplication.cpp index 044acee3667..640ee0c0e45 100644 --- a/tests/benchmarks/corelib/kernel/qcoreapplication/tst_bench_qcoreapplication.cpp +++ b/tests/benchmarks/corelib/kernel/qcoreapplication/tst_bench_qcoreapplication.cpp @@ -10,6 +10,9 @@ Q_OBJECT private slots: void event_posting_benchmark_data(); void event_posting_benchmark(); + + void event_posting_multiple_objects_benchmark_data(); + void event_posting_multiple_objects_benchmark(); }; void tst_QCoreApplication::event_posting_benchmark_data() @@ -39,6 +42,29 @@ void tst_QCoreApplication::event_posting_benchmark() } } +void tst_QCoreApplication::event_posting_multiple_objects_benchmark_data() +{ + event_posting_benchmark_data(); +} + +void tst_QCoreApplication::event_posting_multiple_objects_benchmark() +{ + QFETCH(int, size); + + QObject objects[15]; // The size of the array has not been chosen through any meaningful means + + QRandomGenerator gen; + + // benchmark posting & sending events + QBENCHMARK { + for (int i = 0; i < size; ++i) { + QCoreApplication::postEvent(&objects[gen.bounded(0, int(std::size(objects)))], + new QTimerEvent(i % 10)); + } + QCoreApplication::sendPostedEvents(); + } +} + QTEST_MAIN(tst_QCoreApplication) #include "tst_bench_qcoreapplication.moc"