On Wednesday 16 April 2014 12:55:38 Matthew Woehlke wrote:
> On 2014-04-16 03:18, Volker Krause wrote:
> > On Tuesday 15 April 2014 08:02:56 Thiago Macieira wrote:
> >> In other words: use QBasicAtomicPointer.
> >
> > As mentioned on https://codereview.qt-project.org/#change,83272 Kevin Funk
> > measured the difference between the current approach and using atomics
> > using Olivier's initial benchmark, it's about 4-5x slower for checking if
> > there's a callback set.
@Volker: The 4-5x slower version was the one trying to support the multiple-
callback-scenario (implemented inefficiently, apparently).
> How are you doing that check?
>
> I believe the 'correct' way is 'if (callback)', which calls an inline
> operator that accesses the internal pointer directly, i.e.
> 'callback->operator T*' -> 'callback->_q_value' (which should further be
> the first member, and thus require no additional instructions to access
> versus a raw pointer type).
>
> The only reason this should perform significantly different is if you're
> comparing it to a non-volatile raw pointer... and I'd be very, very
> suspicious of using a non-volatile raw pointer that may be written in
> another thread.
Now, using the straight-forward approach of just defining a
QAtomicPointer<void(*)()> callback; and testing whether this one is set via
'if (callback)', I get much better results using Olivier's testbench.
I get a ~1.5x slowdown with atomic pointers (test4) compared to the version
using raw pointers (test2) on my machine.
New benchmark attached, so everyone can test on his/her own.
If the results can be confirmed, I wonder whether we should actually
reconsider using QInternal for the hooking API...
Greets
PS: Sorry for the confusion with the initial benchmark results (I'm not sure
what I've done there...)
--
Kevin Funk
#include <QtCore/QVarLengthArray>
__attribute__((visibility("default"))) void noop() {};
#include <QtCore/QElapsedTimer>
#include <QtCore/QDebug>
#include <QtCore/QReadLocker>
#include <QtCore/QMutex>
#include <QtCore/QAtomicPointer>
extern void noop();
void (*test1_ptr)() = noop;
void (*test2_ptr)() = 0;
QAtomicPointer<void(*)()> callback;
static int test1() {
test1_ptr();
return 42;
}
static int test2() {
if (test2_ptr)
test2_ptr();
return 42;
}
static int test3() {
noop();
return 42;
}
static int test4() {
if (callback) {
(*callback)();
}
return 42;
}
int main() {
quint64 r;
QElapsedTimer t;
t.start();
for(quint64 i = 0; i < 500 * 1000 * 1000; ++i)
test1();
r = t.elapsed();
qDebug() << "test1: " << r;
t.start();
for(quint64 i = 0; i < 500 * 1000 * 1000; ++i)
test2();
r = t.elapsed();
qDebug() << "test2: " << r;
t.start();
for(quint64 i = 0; i < 500 * 1000 * 1000; ++i)
test3();
r = t.elapsed();
qDebug() << "test3: " << r;
t.start();
for(quint64 i = 0; i < 500 * 1000 * 1000; ++i)
test4();
r = t.elapsed();
qDebug() << "test4: " << r;
t.start();
for(quint64 i = 0; i < 500 * 1000 * 1000; ++i)
test4();
r = t.elapsed();
qDebug() << "test4: " << r;
t.start();
for(quint64 i = 0; i < 500 * 1000 * 1000; ++i)
test3();
r = t.elapsed();
qDebug() << "test3: " << r;
t.start();
for(quint64 i = 0; i < 500 * 1000 * 1000; ++i)
test2();
r = t.elapsed();
qDebug() << "test2: " << r;
t.start();
for(quint64 i = 0; i < 500 * 1000 * 1000; ++i)
test1();
r = t.elapsed();
qDebug() << "test1: " << r;
}
_______________________________________________
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development