summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBradley T. Hughes <bradley.hughes@nokia.com>2010-10-01 08:22:10 (GMT)
committerBradley T. Hughes <bradley.hughes@nokia.com>2010-12-20 15:50:00 (GMT)
commit44cf2baeb07bf48270a6a41c8f1433517130ba01 (patch)
treeef140f11db30e1bc8c1efd182e937e5287c3351d
parent6c1180505a0ac55bfd0eac87c2a61103a8fdec14 (diff)
downloadQt-44cf2baeb07bf48270a6a41c8f1433517130ba01.zip
Qt-44cf2baeb07bf48270a6a41c8f1433517130ba01.tar.gz
Qt-44cf2baeb07bf48270a6a41c8f1433517130ba01.tar.bz2
Track average wait times under our maximum spin time threshold
Further observation shows that spin times slightly over the average wait time produce the best results. This change keeps a heavily weighted average of the wait times under 1.5ms (1.5 times the max spin threshold), and adjusts the spin time to be 150% of the average wait time. Introduce spin time adjustments when spin locking works, and adjust to between 150% of the average wait time and the maximum threshold. Reviewed-by: joao
-rw-r--r--src/corelib/thread/qmutex.cpp24
-rw-r--r--src/corelib/thread/qmutex_p.h1
-rw-r--r--src/corelib/thread/qmutex_unix.cpp2
-rw-r--r--src/corelib/thread/qmutex_win.cpp2
4 files changed, 21 insertions, 8 deletions
diff --git a/src/corelib/thread/qmutex.cpp b/src/corelib/thread/qmutex.cpp
index 03e623f..1009f7b 100644
--- a/src/corelib/thread/qmutex.cpp
+++ b/src/corelib/thread/qmutex.cpp
@@ -453,14 +453,20 @@ void QMutex::lockInternal()
Q_UNUSED(isLocked);
qint64 maximumSpinTime = d->maximumSpinTime;
- qint64 waitTime = elapsedTimer.nsecsElapsed();
+ qint64 averageWaitTime = d->averageWaitTime;
+ qint64 actualWaitTime = elapsedTimer.nsecsElapsed();
+ if (actualWaitTime < (QMutexPrivate::MaximumSpinTimeThreshold * 3 / 2)) {
+ // measure the wait times
+ averageWaitTime = d->averageWaitTime = qMin((averageWaitTime + actualWaitTime) / 2, qint64(QMutexPrivate::MaximumSpinTimeThreshold));
+ }
+
// adjust the spin count when spinning does not benefit contention performance
- if (spinTime + waitTime > QMutexPrivate::MaximumSpinTimeThreshold) {
+ if ((spinTime + actualWaitTime) - qint64(QMutexPrivate::MaximumSpinTimeThreshold) >= qint64(QMutexPrivate::MaximumSpinTimeThreshold)) {
// long waits, stop spinning
d->maximumSpinTime = 0;
- } else if (waitTime < maximumSpinTime) {
- // never spin more than the minimum wait time (otherwise we may perform worse)
- d->maximumSpinTime = waitTime;
+ } else {
+ // allow spinning if wait times decrease, but never spin more than the average wait time (otherwise we may perform worse)
+ d->maximumSpinTime = qBound(qint64(averageWaitTime * 3 / 2), maximumSpinTime / 2, qint64(QMutexPrivate::MaximumSpinTimeThreshold));
}
return;
}
@@ -468,7 +474,13 @@ void QMutex::lockInternal()
QThread::yieldCurrentThread();
} while (d->contenders != 0 || !d->contenders.testAndSetAcquire(0, 1));
- // spinning is working, do not change the spin time
+ // spinning is working, do not change the spin time (unless we are using much less time than allowed to spin)
+ qint64 maximumSpinTime = d->maximumSpinTime;
+ qint64 spinTime = elapsedTimer.nsecsElapsed();
+ if (spinTime < maximumSpinTime / 2) {
+ // we are using much less time than we need, adjust the limit
+ d->maximumSpinTime = qBound(qint64(d->averageWaitTime * 3 / 2), maximumSpinTime / 2, qint64(QMutexPrivate::MaximumSpinTimeThreshold));
+ }
}
/*!
diff --git a/src/corelib/thread/qmutex_p.h b/src/corelib/thread/qmutex_p.h
index fa6e879..9d40bea 100644
--- a/src/corelib/thread/qmutex_p.h
+++ b/src/corelib/thread/qmutex_p.h
@@ -75,6 +75,7 @@ public:
// 1ms = 1000000ns
enum { MaximumSpinTimeThreshold = 1000000 };
volatile qint64 maximumSpinTime;
+ volatile qint64 averageWaitTime;
Qt::HANDLE owner;
uint count;
diff --git a/src/corelib/thread/qmutex_unix.cpp b/src/corelib/thread/qmutex_unix.cpp
index 48014cc..0e09ea0 100644
--- a/src/corelib/thread/qmutex_unix.cpp
+++ b/src/corelib/thread/qmutex_unix.cpp
@@ -74,7 +74,7 @@ static void report_error(int code, const char *where, const char *what)
QMutexPrivate::QMutexPrivate(QMutex::RecursionMode mode)
- : QMutexData(mode), maximumSpinTime(MaximumSpinTimeThreshold), owner(0), count(0)
+ : QMutexData(mode), maximumSpinTime(MaximumSpinTimeThreshold), averageWaitTime(0), owner(0), count(0)
{
#if defined(Q_OS_MAC)
kern_return_t r = semaphore_create(mach_task_self(), &mach_semaphore, SYNC_POLICY_FIFO, 0);
diff --git a/src/corelib/thread/qmutex_win.cpp b/src/corelib/thread/qmutex_win.cpp
index 89e8b87..a759caa 100644
--- a/src/corelib/thread/qmutex_win.cpp
+++ b/src/corelib/thread/qmutex_win.cpp
@@ -48,7 +48,7 @@
QT_BEGIN_NAMESPACE
QMutexPrivate::QMutexPrivate(QMutex::RecursionMode mode)
- : QMutexData(mode), maximumSpinTime(MaximumSpinTimeThreshold), owner(0), count(0)
+ : QMutexData(mode), maximumSpinTime(MaximumSpinTimeThreshold), averageWaitTime(0), owner(0), count(0)
{
event = CreateEvent(0, FALSE, FALSE, 0);
if (!event)