Enable and extend the qtimer_vs_qmetaobject benchmark

This benchmark was not compiled, and it only covered some parts of the
API. Enable it, and also measure the performance of PMF and Functor API
variants, for both QTimer::singleShot and QMetaObject::invokeMethod.

This uncovers that the zero-timeout optimization for the singleShot is
not applied to the PMF and Functor API variants:

********* Start testing of qtimer_vs_qmetaobject *********
Config: Using QtTest library 5.11.0, Qt 5.11.0 (x86_64-little_endian-lp64 shared (dynamic) release build; by GCC 7.2.1 20171224)
PASS   : qtimer_vs_qmetaobject::initTestCase()
PASS   : qtimer_vs_qmetaobject::bench(singleShot_slot)
RESULT : qtimer_vs_qmetaobject::bench():"singleShot_slot":
     5.20 msecs per iteration (total: 520, iterations: 100)
PASS   : qtimer_vs_qmetaobject::bench(singleShot_pmf)
RESULT : qtimer_vs_qmetaobject::bench():"singleShot_pmf":
     75.93 msecs per iteration (total: 7,594, iterations: 100)
PASS   : qtimer_vs_qmetaobject::bench(singleShot_functor)
RESULT : qtimer_vs_qmetaobject::bench():"singleShot_functor":
     77.90 msecs per iteration (total: 7,790, iterations: 100)
PASS   : qtimer_vs_qmetaobject::bench(singleShot_functor_noctx)
RESULT : qtimer_vs_qmetaobject::bench():"singleShot_functor_noctx":
     76.23 msecs per iteration (total: 7,624, iterations: 100)
PASS   : qtimer_vs_qmetaobject::bench(invokeMethod_string)
RESULT : qtimer_vs_qmetaobject::bench():"invokeMethod_string":
     4.99 msecs per iteration (total: 499, iterations: 100)
PASS   : qtimer_vs_qmetaobject::bench(invokeMethod_pmf)
RESULT : qtimer_vs_qmetaobject::bench():"invokeMethod_pmf":
     5.37 msecs per iteration (total: 538, iterations: 100)
PASS   : qtimer_vs_qmetaobject::bench(invokeMethod_functor)
RESULT : qtimer_vs_qmetaobject::bench():"invokeMethod_functor":
     4.74 msecs per iteration (total: 474, iterations: 100)
PASS   : qtimer_vs_qmetaobject::cleanupTestCase()
Totals: 9 passed, 0 failed, 0 skipped, 0 blacklisted, 50220ms
********* Finished testing of qtimer_vs_qmetaobject *********

Change-Id: I46336613188317124804638627f07eb135dc0286
Reviewed-by: Olivier Goffart (Woboq GmbH) <ogoffart@woboq.com>
This commit is contained in:
Milian Wolff 2018-01-11 17:31:18 +01:00
parent 742a07ece1
commit 4413f7070a
2 changed files with 56 additions and 14 deletions

View File

@ -5,7 +5,8 @@ SUBDIRS = \
qmetatype \
qobject \
qvariant \
qcoreapplication
qcoreapplication \
qtimer_vs_qmetaobject
!qtHaveModule(widgets): SUBDIRS -= \
qmetaobject \

View File

@ -35,8 +35,8 @@ class qtimer_vs_qmetaobject : public QObject
{
Q_OBJECT
private slots:
void testZeroTimerSingleShot();
void testQueuedInvokeMethod();
void bench();
void bench_data();
};
class InvokeCounter : public QObject {
@ -53,28 +53,69 @@ protected:
int count;
};
void qtimer_vs_qmetaobject::testZeroTimerSingleShot()
void qtimer_vs_qmetaobject::bench()
{
QFETCH(int, type);
std::function<void(InvokeCounter*)> invoke;
if (type == 0) {
invoke = [](InvokeCounter* invokeCounter) {
QTimer::singleShot(0, invokeCounter, SLOT(invokeSlot()));
};
} else if (type == 1) {
invoke = [](InvokeCounter* invokeCounter) {
QTimer::singleShot(0, invokeCounter, &InvokeCounter::invokeSlot);
};
} else if (type == 2) {
invoke = [](InvokeCounter* invokeCounter) {
QTimer::singleShot(0, invokeCounter, [invokeCounter]() {
invokeCounter->invokeSlot();
});
};
} else if (type == 3) {
invoke = [](InvokeCounter* invokeCounter) {
QTimer::singleShot(0, [invokeCounter]() {
invokeCounter->invokeSlot();
});
};
} else if (type == 4) {
invoke = [](InvokeCounter* invokeCounter) {
QMetaObject::invokeMethod(invokeCounter, "invokeSlot", Qt::QueuedConnection);
};
} else if (type == 5) {
invoke = [](InvokeCounter* invokeCounter) {
QMetaObject::invokeMethod(invokeCounter, &InvokeCounter::invokeSlot, Qt::QueuedConnection);
};
} else if (type == 6) {
invoke = [](InvokeCounter* invokeCounter) {
QMetaObject::invokeMethod(invokeCounter, [invokeCounter]() {
invokeCounter->invokeSlot();
}, Qt::QueuedConnection);
};
} else {
QFAIL("unhandled data tag");
}
QBENCHMARK {
InvokeCounter invokeCounter;
for(int i = 0; i < INVOKE_COUNT; ++i) {
QTimer::singleShot(0, &invokeCounter, SLOT(invokeSlot()));
invoke(&invokeCounter);
}
QTestEventLoop::instance().enterLoop(10);
QVERIFY(!QTestEventLoop::instance().timeout());
}
}
void qtimer_vs_qmetaobject::testQueuedInvokeMethod()
void qtimer_vs_qmetaobject::bench_data()
{
QBENCHMARK {
InvokeCounter invokeCounter;
for(int i = 0; i < INVOKE_COUNT; ++i) {
QMetaObject::invokeMethod(&invokeCounter, "invokeSlot", Qt::QueuedConnection);
}
QTestEventLoop::instance().enterLoop(10);
QVERIFY(!QTestEventLoop::instance().timeout());
}
QTest::addColumn<int>("type");
QTest::addRow("singleShot_slot") << 0;
QTest::addRow("singleShot_pmf") << 1;
QTest::addRow("singleShot_functor") << 2;
QTest::addRow("singleShot_functor_noctx") << 3;
QTest::addRow("invokeMethod_string") << 4;
QTest::addRow("invokeMethod_pmf") << 5;
QTest::addRow("invokeMethod_functor") << 6;
}