diff options
author | Bradley T. Hughes <bradley.hughes@nokia.com> | 2010-09-28 09:39:17 (GMT) |
---|---|---|
committer | Bradley T. Hughes <bradley.hughes@nokia.com> | 2010-12-20 14:27:19 (GMT) |
commit | 33b015ae5fe561e48130b07e1ae320131cec3505 (patch) | |
tree | e42e211d7122b3888d7acd4475749b34be61a1a7 /tests/benchmarks/corelib | |
parent | df5403e48df3ab57924a6b85d9cbaa95e3c5e766 (diff) | |
download | Qt-33b015ae5fe561e48130b07e1ae320131cec3505.zip Qt-33b015ae5fe561e48130b07e1ae320131cec3505.tar.gz Qt-33b015ae5fe561e48130b07e1ae320131cec3505.tar.bz2 |
Add a benchmark for contended and uncontended QMutex performance
This benchmark also includes the same benchmark for the native type for
comparison.
Reviewed-by: joao
Diffstat (limited to 'tests/benchmarks/corelib')
-rw-r--r-- | tests/benchmarks/corelib/thread/qmutex/qmutex.pro | 2 | ||||
-rw-r--r-- | tests/benchmarks/corelib/thread/qmutex/tst_qmutex.cpp | 272 |
2 files changed, 261 insertions, 13 deletions
diff --git a/tests/benchmarks/corelib/thread/qmutex/qmutex.pro b/tests/benchmarks/corelib/thread/qmutex/qmutex.pro index eda2f11..8fda5fa 100644 --- a/tests/benchmarks/corelib/thread/qmutex/qmutex.pro +++ b/tests/benchmarks/corelib/thread/qmutex/qmutex.pro @@ -1,6 +1,6 @@ load(qttest_p4) TEMPLATE = app TARGET = tst_bench_qmutex - +QT -= gui SOURCES += tst_qmutex.cpp diff --git a/tests/benchmarks/corelib/thread/qmutex/tst_qmutex.cpp b/tests/benchmarks/corelib/thread/qmutex/tst_qmutex.cpp index fded508..9ed5d55 100644 --- a/tests/benchmarks/corelib/thread/qmutex/tst_qmutex.cpp +++ b/tests/benchmarks/corelib/thread/qmutex/tst_qmutex.cpp @@ -39,34 +39,85 @@ ** ****************************************************************************/ -#include <qtest.h> -#include <QtCore> +#include <QtCore/QtCore> +#include <QtTest/QtTest> #include <math.h> -//TESTED_FILES= +#ifdef Q_OS_UNIX +# include <pthread.h> +# include <errno.h> +typedef pthread_mutex_t NativeMutexType; +void NativeMutexInitialize(NativeMutexType *mutex) +{ + pthread_mutex_init(mutex, NULL); +} +void NativeMutexDestroy(NativeMutexType *mutex) +{ + pthread_mutex_destroy(mutex); +} +void NativeMutexLock(NativeMutexType *mutex) +{ + pthread_mutex_lock(mutex); +} +void NativeMutexUnlock(NativeMutexType *mutex) +{ + pthread_mutex_unlock(mutex); +} +#elif defined(Q_OS_WIN) +# define _WIN32_WINNT 0x0400 +# include <windows.h> +typedef CRITICAL_SECTION NativeMutexType; +void NativeMutexInitialize(NativeMutexType *mutex) +{ + InitializeCriticalSection(mutex); +} +void NativeMutexDestroy(NativeMutexType *mutex) +{ + DeleteCriticalSection(mutex); +} +void NativeMutexLock(NativeMutexType *mutex) +{ + EnterCriticalSection(mutex); +} +void NativeMutexUnlock(NativeMutexType *mutex) +{ + LeaveCriticalSection(mutex); +} +#endif +//TESTED_FILES= class tst_QMutex : public QObject { Q_OBJECT + int threadCount; + public: - tst_QMutex(); - virtual ~tst_QMutex(); + tst_QMutex() + { + // at least 2 threads, even on single cpu/core machines + threadCount = qMax(2, QThread::idealThreadCount()); + qDebug("thread count: %d", threadCount); + } private slots: void noThread_data(); void noThread(); -}; -tst_QMutex::tst_QMutex() -{ -} + void uncontendedNative(); + void uncontendedQMutex(); + void uncontendedQMutexLocker(); -tst_QMutex::~tst_QMutex() -{ -} + void contendedNative_data(); + void contendedQMutex_data() { contendedNative_data(); } + void contendedQMutexLocker_data() { contendedNative_data(); } + + void contendedNative(); + void contendedQMutex(); + void contendedQMutexLocker(); +}; void tst_QMutex::noThread_data() { @@ -127,5 +178,202 @@ void tst_QMutex::noThread() QCOMPARE(int(count), N); } +void tst_QMutex::uncontendedNative() +{ + NativeMutexType mutex; + NativeMutexInitialize(&mutex); + QBENCHMARK { + NativeMutexLock(&mutex); + NativeMutexUnlock(&mutex); + } + NativeMutexDestroy(&mutex); +} + +void tst_QMutex::uncontendedQMutex() +{ + QMutex mutex; + QBENCHMARK { + mutex.lock(); + mutex.unlock(); + } +} + +void tst_QMutex::uncontendedQMutexLocker() +{ + QMutex mutex; + QBENCHMARK { + QMutexLocker locker(&mutex); + } +} + +void tst_QMutex::contendedNative_data() +{ + QTest::addColumn<int>("iterations"); + QTest::addColumn<int>("msleepDuration"); + QTest::newRow("-1") << 100 << -1; + QTest::newRow("0") << 100 << 0; + QTest::newRow("1") << 10 << 1; + QTest::newRow("2") << 10 << 2; +} + +class NativeMutexThread : public QThread +{ + QSemaphore *semaphore1, *semaphore2; + NativeMutexType *mutex; + int iterations, msleepDuration; +public: + bool done; + NativeMutexThread(QSemaphore *semaphore1, QSemaphore *semaphore2, NativeMutexType *mutex, int iterations, int msleepDuration) + : semaphore1(semaphore1), semaphore2(semaphore2), mutex(mutex), iterations(iterations), msleepDuration(msleepDuration), done(false) + { } + void run() { + forever { + semaphore1->acquire(); + if (done) + break; + for (int i = 0; i < iterations; ++i) { + NativeMutexLock(mutex); + if (msleepDuration >= 0) + msleep(msleepDuration); + NativeMutexUnlock(mutex); + } + semaphore2->release(); + } + } +}; + +void tst_QMutex::contendedNative() +{ + QFETCH(int, iterations); + QFETCH(int, msleepDuration); + + QSemaphore semaphore1, semaphore2; + NativeMutexType mutex; + NativeMutexInitialize(&mutex); + + QVector<NativeMutexThread *> threads(threadCount); + for (int i = 0; i < threads.count(); ++i) { + threads[i] = new NativeMutexThread(&semaphore1, &semaphore2, &mutex, iterations, msleepDuration); + threads[i]->start(); + } + + QBENCHMARK { + semaphore1.release(threadCount); + semaphore2.acquire(threadCount); + } + + for (int i = 0; i < threads.count(); ++i) + threads[i]->done = true; + semaphore1.release(threadCount); + for (int i = 0; i < threads.count(); ++i) + threads[i]->wait(); + qDeleteAll(threads); + + NativeMutexDestroy(&mutex); +} + +class QMutexThread : public QThread +{ + QSemaphore *semaphore1, *semaphore2; + QMutex *mutex; + int iterations, msleepDuration; +public: + bool done; + QMutexThread(QSemaphore *semaphore1, QSemaphore *semaphore2, QMutex *mutex, int iterations, int msleepDuration) + : semaphore1(semaphore1), semaphore2(semaphore2), mutex(mutex), iterations(iterations), msleepDuration(msleepDuration), done(false) + { } + void run() { + forever { + semaphore1->acquire(); + if (done) + break; + for (int i = 0; i < iterations; ++i) { + mutex->lock(); + if (msleepDuration >= 0) + msleep(msleepDuration); + mutex->unlock(); + } + semaphore2->release(); + } + } +}; + +void tst_QMutex::contendedQMutex() +{ + QFETCH(int, iterations); + QFETCH(int, msleepDuration); + QSemaphore semaphore1, semaphore2; + QMutex mutex; + + QVector<QMutexThread *> threads(threadCount); + for (int i = 0; i < threads.count(); ++i) { + threads[i] = new QMutexThread(&semaphore1, &semaphore2, &mutex, iterations, msleepDuration); + threads[i]->start(); + } + + QBENCHMARK { + semaphore1.release(threadCount); + semaphore2.acquire(threadCount); + } + + for (int i = 0; i < threads.count(); ++i) + threads[i]->done = true; + semaphore1.release(threadCount); + for (int i = 0; i < threads.count(); ++i) + threads[i]->wait(); + qDeleteAll(threads); +} + +class QMutexLockerThread : public QThread +{ + QSemaphore *semaphore1, *semaphore2; + QMutex *mutex; + int iterations, msleepDuration; +public: + bool done; + QMutexLockerThread(QSemaphore *semaphore1, QSemaphore *semaphore2, QMutex *mutex, int iterations, int msleepDuration) + : semaphore1(semaphore1), semaphore2(semaphore2), mutex(mutex), iterations(iterations), msleepDuration(msleepDuration), done(false) + { } + void run() { + forever { + semaphore1->acquire(); + if (done) + break; + for (int i = 0; i < iterations; ++i) { + QMutexLocker locker(mutex); + if (msleepDuration >= 0) + msleep(msleepDuration); + } + semaphore2->release(); + } + } +}; + +void tst_QMutex::contendedQMutexLocker() +{ + QFETCH(int, iterations); + QFETCH(int, msleepDuration); + QSemaphore semaphore1, semaphore2; + QMutex mutex; + + QVector<QMutexLockerThread *> threads(threadCount); + for (int i = 0; i < threads.count(); ++i) { + threads[i] = new QMutexLockerThread(&semaphore1, &semaphore2, &mutex, iterations, msleepDuration); + threads[i]->start(); + } + + QBENCHMARK { + semaphore1.release(threadCount); + semaphore2.acquire(threadCount); + } + + for (int i = 0; i < threads.count(); ++i) + threads[i]->done = true; + semaphore1.release(threadCount); + for (int i = 0; i < threads.count(); ++i) + threads[i]->wait(); + qDeleteAll(threads); +} + QTEST_MAIN(tst_QMutex) #include "tst_qmutex.moc" |