diff options
author | Marc Mutz <marc.mutz@kdab.com> | 2019-09-12 15:52:46 +0200 |
---|---|---|
committer | Marc Mutz <marc.mutz@qt.io> | 2021-11-26 18:28:50 +0100 |
commit | 6a1a9365371f6e456bafe5120467c100cf7ca105 (patch) | |
tree | 3d0be19953dd816109ddf38ee0e95200ab91bc4c /tests/benchmarks/corelib/thread/qwaitcondition | |
parent | b5216c89658e29131dc97b7c6df06cb54476bc02 (diff) |
QWaitCondition: also benchmark std::condition_variable{,_any}
Results on my machine (only forever results):
********* Start testing of tst_QWaitCondition *********
Config: Using QtTest library 6.3.0, Qt 6.3.0 (x86_64-little_endian-lp64 shared (dynamic) release build; by GCC 11.2.1 20211115), ubuntu 20.04
PASS : tst_QWaitCondition::oscillate_QWaitCondition_QMutex(forever)
RESULT : tst_QWaitCondition::oscillate_QWaitCondition_QMutex():"forever":
637 msecs per iteration (total: 637, iterations: 1)
PASS : tst_QWaitCondition::oscillate_QWaitCondition_QReadWriteLock(forever)
RESULT : tst_QWaitCondition::oscillate_QWaitCondition_QReadWriteLock():"forever":
909 msecs per iteration (total: 909, iterations: 1)
PASS : tst_QWaitCondition::oscillate_std_condition_variable_std_mutex(forever)
RESULT : tst_QWaitCondition::oscillate_std_condition_variable_std_mutex():"forever":
331 msecs per iteration (total: 331, iterations: 1)
PASS : tst_QWaitCondition::oscillate_std_condition_variable_any_QMutex(forever)
RESULT : tst_QWaitCondition::oscillate_std_condition_variable_any_QMutex():"forever":
627 msecs per iteration (total: 627, iterations: 1)
PASS : tst_QWaitCondition::oscillate_std_condition_variable_any_QReadWriteLock(forever)
RESULT : tst_QWaitCondition::oscillate_std_condition_variable_any_QReadWriteLock():"forever":
913 msecs per iteration (total: 913, iterations: 1)
~331 vs. ~630ms. A pretty significant win (2x).
MÃ¥rten noticed that on Windows, condition_variable::wait_for(x, 0ms)
will not unlock the mutex, which, however, the program requires, so
use a 1ns timeout instead.
Drive-by fixes:
- add override to run() reimplementations
- fix type of timeout member variable (was int, should be unsigned long)
- fix naming of test functions to distinguish better between QMutex
and std::mutex
Change-Id: Ib92310f15fbd58258b2043504642be5f0b860f39
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'tests/benchmarks/corelib/thread/qwaitcondition')
-rw-r--r-- | tests/benchmarks/corelib/thread/qwaitcondition/tst_bench_qwaitcondition.cpp | 96 |
1 files changed, 83 insertions, 13 deletions
diff --git a/tests/benchmarks/corelib/thread/qwaitcondition/tst_bench_qwaitcondition.cpp b/tests/benchmarks/corelib/thread/qwaitcondition/tst_bench_qwaitcondition.cpp index 19d3964c7a..3612b8784b 100644 --- a/tests/benchmarks/corelib/thread/qwaitcondition/tst_bench_qwaitcondition.cpp +++ b/tests/benchmarks/corelib/thread/qwaitcondition/tst_bench_qwaitcondition.cpp @@ -30,7 +30,12 @@ #include <QTest> #include <math.h> +#include <condition_variable> +#include <mutex> +#include <limits.h> + +using namespace std::chrono_literals; class tst_QWaitCondition : public QObject { @@ -42,24 +47,67 @@ public: } private slots: + void oscillate_QWaitCondition_QMutex_data() { oscillate_mutex_data(); } + void oscillate_QWaitCondition_QMutex(); + void oscillate_QWaitCondition_QReadWriteLock_data() { oscillate_mutex_data(); } + void oscillate_QWaitCondition_QReadWriteLock(); + void oscillate_std_condition_variable_std_mutex_data() { oscillate_mutex_data(); } + void oscillate_std_condition_variable_std_mutex(); + void oscillate_std_condition_variable_any_QMutex_data() { oscillate_mutex_data(); } + void oscillate_std_condition_variable_any_QMutex(); + void oscillate_std_condition_variable_any_QReadWriteLock_data() { oscillate_mutex_data(); } + void oscillate_std_condition_variable_any_QReadWriteLock(); + +private: void oscillate_mutex_data(); - void oscillate_mutex(); - void oscillate_writelock_data(); - void oscillate_writelock(); }; int turn; const int threadCount = 10; QWaitCondition cond; +std::condition_variable cv; +std::condition_variable_any cva; -template <class Mutex, class Locker> +template <typename Cond> +Cond *get(); + +template <> std::condition_variable *get() { return &cv; } +template <> std::condition_variable_any *get() { return &cva; } + +template <class Cond, class Mutex, class Locker> class OscillateThread : public QThread { public: Mutex *mutex; int m_threadid; - int timeout; + unsigned long timeout; + + void run() override + { + for (int count = 0; count < 5000; ++count) { + Locker lock(*mutex); + while (m_threadid != turn) { + if (timeout == ULONG_MAX) + get<Cond>()->wait(lock); + else if (timeout == 0) // Windows doesn't unlock the mutex with a zero timeout + get<Cond>()->wait_for(lock, 1ns); + else + get<Cond>()->wait_for(lock, timeout * 1ms); + } + turn = (turn+1) % threadCount; + get<Cond>()->notify_all(); + } + } +}; + +template <class Mutex, class Locker> +class OscillateThread<QWaitCondition, Mutex, Locker> : public QThread +{ +public: + Mutex *mutex; + int m_threadid; + unsigned long timeout; void run() override { @@ -75,10 +123,10 @@ public: } }; -template <class Mutex, class Locker> +template <class Cond, class Mutex, class Locker> void oscillate(unsigned long timeout) { - OscillateThread<Mutex, Locker> thrd[threadCount]; + OscillateThread<Cond, Mutex, Locker> thrd[threadCount]; Mutex m; for (int i = 0; i < threadCount; ++i) { thrd[i].mutex = &m; @@ -107,21 +155,43 @@ void tst_QWaitCondition::oscillate_mutex_data() QTest::newRow("forever") << ULONG_MAX; } -void tst_QWaitCondition::oscillate_mutex() +void tst_QWaitCondition::oscillate_QWaitCondition_QMutex() { QFETCH(unsigned long, timeout); - oscillate<QMutex, QMutexLocker<QMutex>>(timeout); + oscillate<QWaitCondition, QMutex, QMutexLocker<QMutex>>(timeout); } -void tst_QWaitCondition::oscillate_writelock_data() +void tst_QWaitCondition::oscillate_QWaitCondition_QReadWriteLock() { - oscillate_mutex_data(); + QFETCH(unsigned long, timeout); + oscillate<QWaitCondition, QReadWriteLock, QWriteLocker>(timeout); } -void tst_QWaitCondition::oscillate_writelock() +void tst_QWaitCondition::oscillate_std_condition_variable_std_mutex() { QFETCH(unsigned long, timeout); - oscillate<QReadWriteLock, QWriteLocker>(timeout); + oscillate<std::condition_variable, std::mutex, std::unique_lock<std::mutex>>(timeout); +} + + +void tst_QWaitCondition::oscillate_std_condition_variable_any_QMutex() +{ + QFETCH(unsigned long, timeout); + oscillate<std::condition_variable_any, QMutex, std::unique_lock<QMutex>>(timeout); +} + + +void tst_QWaitCondition::oscillate_std_condition_variable_any_QReadWriteLock() +{ + QFETCH(unsigned long, timeout); + + struct WriteLocker : QWriteLocker { + // adapt to BasicLockable + explicit WriteLocker(QReadWriteLock &m) : QWriteLocker{&m} {} + void lock() { relock(); } + }; + + oscillate<std::condition_variable_any, QReadWriteLock, WriteLocker>(timeout); } QTEST_MAIN(tst_QWaitCondition) |