From 6a1a9365371f6e456bafe5120467c100cf7ca105 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Thu, 12 Sep 2019 15:52:46 +0200 Subject: QWaitCondition: also benchmark std::condition_variable{,_any} MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Lars Knoll --- .../qwaitcondition/tst_bench_qwaitcondition.cpp | 96 +++++++++++++++++++--- 1 file changed, 83 insertions(+), 13 deletions(-) (limited to 'tests/benchmarks/corelib/thread/qwaitcondition') 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 #include +#include +#include +#include + +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 +template +Cond *get(); + +template <> std::condition_variable *get() { return &cv; } +template <> std::condition_variable_any *get() { return &cva; } + +template 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()->wait(lock); + else if (timeout == 0) // Windows doesn't unlock the mutex with a zero timeout + get()->wait_for(lock, 1ns); + else + get()->wait_for(lock, timeout * 1ms); + } + turn = (turn+1) % threadCount; + get()->notify_all(); + } + } +}; + +template +class OscillateThread : public QThread +{ +public: + Mutex *mutex; + int m_threadid; + unsigned long timeout; void run() override { @@ -75,10 +123,10 @@ public: } }; -template +template void oscillate(unsigned long timeout) { - OscillateThread thrd[threadCount]; + OscillateThread 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>(timeout); + oscillate>(timeout); } -void tst_QWaitCondition::oscillate_writelock_data() +void tst_QWaitCondition::oscillate_QWaitCondition_QReadWriteLock() { - oscillate_mutex_data(); + QFETCH(unsigned long, timeout); + oscillate(timeout); } -void tst_QWaitCondition::oscillate_writelock() +void tst_QWaitCondition::oscillate_std_condition_variable_std_mutex() { QFETCH(unsigned long, timeout); - oscillate(timeout); + oscillate>(timeout); +} + + +void tst_QWaitCondition::oscillate_std_condition_variable_any_QMutex() +{ + QFETCH(unsigned long, timeout); + oscillate>(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(timeout); } QTEST_MAIN(tst_QWaitCondition) -- cgit v1.2.3