on the importance of doing nothing
When you're programming, always make sure you question *why* things are done. Qt provides three functions, helpfully named qMalloc/qRealloc/qFree. Despite the 'q' in front of their names, these functions do absolutely nothing useful, they just wrap around their stdlib friends. This was originally done to enable replacement of the allocator inside Qt (but there are better ways to do that, without getting sidetracked from my central point), but in reality, doesn't have much use. That's why I'm trying to deprecate them.
Now, you might ask, "what impact could a simple function call have, anyway"? I'm glad you asked. Benchmark time (spoiler for the lazy: ~10% extra overhead for small allocation sizes, ~0-5% for larger allocation sizes).
virgin:~/mallocbench% cat main.cpp
#include <QtCore>
#include <qtest.h>
#include <qcoreapplication.h>
#include <qdatetime.h>
class MallocBenchmark : public QObject
{
Q_OBJECT
private slots:
void qtMalloc();
void qtMalloc_data();
void regularMalloc();
void regularMalloc_data();
};
void MallocBenchmark::qtMalloc_data()
{
QTest::addColumn<int>("size");
QTest::newRow("1") << 1;
QTest::newRow("10") << 1;
QTest::newRow("100") << 100;
QTest::newRow("10000") << 10000;
QTest::newRow("1000000") << 1000000;
QTest::newRow("10000000") << 10000000;
}
void MallocBenchmark::qtMalloc()
{
QFETCH(int, size);
QBENCHMARK {
void *p = ::qMalloc(size);
::qFree(p);
}
}
void MallocBenchmark::regularMalloc_data()
{
qtMalloc_data();
}
void MallocBenchmark::regularMalloc()
{
QFETCH(int, size);
QBENCHMARK {
void *p = malloc(size);
free(p);
}
}
QTEST_MAIN(MallocBenchmark)
#include "main.moc"
And now, the results on my machine:
********* Start testing of MallocBenchmark *********
Config: Using QTest library 5.0.0, Qt 5.0.0
PASS : MallocBenchmark::initTestCase()
RESULT : MallocBenchmark::qtMalloc():"1":
0.000059 msecs per iteration (total: 62, iterations: 1048576)
RESULT : MallocBenchmark::qtMalloc():"10":
0.000062 msecs per iteration (total: 66, iterations: 1048576)
RESULT : MallocBenchmark::qtMalloc():"100":
0.000087 msecs per iteration (total: 92, iterations: 1048576)
RESULT : MallocBenchmark::qtMalloc():"10000":
0.000083 msecs per iteration (total: 88, iterations: 1048576)
RESULT : MallocBenchmark::qtMalloc():"1000000":
0.0043 msecs per iteration (total: 72, iterations: 16384)
RESULT : MallocBenchmark::qtMalloc():"10000000":
0.0063 msecs per iteration (total: 52, iterations: 8192)
PASS : MallocBenchmark::qtMalloc()
RESULT : MallocBenchmark::regularMalloc():"1":
0.000053 msecs per iteration (total: 56, iterations: 1048576)
RESULT : MallocBenchmark::regularMalloc():"10":
0.000051 msecs per iteration (total: 54, iterations: 1048576)
RESULT : MallocBenchmark::regularMalloc():"100":
0.000082 msecs per iteration (total: 86, iterations: 1048576)
RESULT : MallocBenchmark::regularMalloc():"10000":
0.000076 msecs per iteration (total: 80, iterations: 1048576)
RESULT : MallocBenchmark::regularMalloc():"1000000":
0.0043 msecs per iteration (total: 71, iterations: 16384)
RESULT : MallocBenchmark::regularMalloc():"10000000":
0.0060 msecs per iteration (total: 99, iterations: 16384)
PASS : MallocBenchmark::regularMalloc()
PASS : MallocBenchmark::cleanupTestCase()
Totals: 4 passed, 0 failed, 0 skipped
********* Finished testing of MallocBenchmark *********
Around 10% extra time per iteration on smaller allocation sizes, 0-5% on larger sizes (most likely explained by glibc falling back to using mmap for larger allocations, which is going to take an awful long time compared to a single function call). These, obviously, aren't huge numbers. But remember: this is overhead you're taking for no reason at all. Don't do it. Your CPU cycles will thank me.