qt 6.5.1 original

This commit is contained in:
kleuter
2023-10-29 23:33:08 +01:00
parent 71d22ab6b0
commit 85d238dfda
21202 changed files with 5499099 additions and 0 deletions

View File

@ -0,0 +1,16 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
add_subdirectory(containers-associative)
add_subdirectory(containers-sequential)
add_subdirectory(qcontiguouscache)
add_subdirectory(qcryptographichash)
add_subdirectory(qhash)
add_subdirectory(qlist)
add_subdirectory(qmap)
add_subdirectory(qrect)
add_subdirectory(qringbuffer)
add_subdirectory(qset)
add_subdirectory(qsharedpointer)
add_subdirectory(qstack)
add_subdirectory(qvector)

View File

@ -0,0 +1,13 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
#####################################################################
## tst_bench_containers_associative Binary:
#####################################################################
qt_internal_add_benchmark(tst_bench_containers_associative
SOURCES
tst_bench_containers_associative.cpp
LIBRARIES
Qt::Test
)

View File

@ -0,0 +1,108 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include <QString>
#include <QMap>
#include <QHash>
#include <qtest.h>
class tst_associative_containers : public QObject
{
Q_OBJECT
private slots:
void insert_data();
void insert();
void lookup_data();
void lookup();
};
template <typename T>
void testInsert(int size)
{
T container;
QBENCHMARK {
for (int i = 0; i < size; ++i)
container.insert(i, i);
}
}
void tst_associative_containers::insert_data()
{
QTest::addColumn<bool>("useHash");
QTest::addColumn<int>("size");
for (int size = 10; size < 20000; size += 100) {
const QByteArray sizeString = QByteArray::number(size);
QTest::newRow(QByteArray("hash--" + sizeString).constData()) << true << size;
QTest::newRow(QByteArray("map--" + sizeString).constData()) << false << size;
}
}
void tst_associative_containers::insert()
{
QFETCH(bool, useHash);
QFETCH(int, size);
QHash<int, int> testHash;
QMap<int, int> testMap;
if (useHash) {
testInsert<QHash<int, int> >(size);
} else {
testInsert<QMap<int, int> >(size);
}
}
void tst_associative_containers::lookup_data()
{
// setReportType(LineChartReport);
// setChartTitle("Time to call value(), with an increasing number of items in the container");
QTest::addColumn<bool>("useHash");
QTest::addColumn<int>("size");
for (int size = 10; size < 20000; size += 100) {
const QByteArray sizeString = QByteArray::number(size);
QTest::newRow(QByteArray("hash--" + sizeString).constData()) << true << size;
QTest::newRow(QByteArray("map--" + sizeString).constData()) << false << size;
}
}
template <typename T>
void testLookup(int size)
{
T container;
for (int i = 0; i < size; ++i)
container.insert(i, i);
int val;
QBENCHMARK {
for (int i = 0; i < size; ++i)
val = container.value(i);
}
Q_UNUSED(val);
}
void tst_associative_containers::lookup()
{
QFETCH(bool, useHash);
QFETCH(int, size);
if (useHash) {
testLookup<QHash<int, int> >(size);
} else {
testLookup<QMap<int, int> >(size);
}
}
QTEST_MAIN(tst_associative_containers)
#include "tst_bench_containers_associative.moc"

View File

@ -0,0 +1,13 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
#####################################################################
## tst_bench_containers-sequential Binary:
#####################################################################
qt_internal_add_benchmark(tst_bench_containers_sequential
SOURCES
tst_bench_containers_sequential.cpp
LIBRARIES
Qt::Test
)

View File

@ -0,0 +1,223 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
// This file contains benchmarks for comparing QList against std::vector
#include <QtCore>
#include <QList>
#include <vector>
#include <qtest.h>
template <typename T> // T is the item type
class UseCases {
public:
virtual ~UseCases() {}
// Use case: Insert \a size items into the vector.
virtual void insert(int size) = 0;
// Use case: Lookup \a size items from the vector.
virtual void lookup(int size) = 0;
};
template <typename T>
T * f(T *ts) // dummy function to prevent code from being optimized away by the compiler
{
return ts;
}
// This subclass implements the use cases using QList as efficiently as possible.
template<typename T>
class UseCases_QList : public UseCases<T>
{
void insert(int size) override
{
QList<T> v;
T t{};
QBENCHMARK {
for (int i = 0; i < size; ++i)
v.append(t);
}
}
void lookup(int size) override
{
QList<T> v;
T t{};
for (int i = 0; i < size; ++i)
v.append(t);
T *ts = new T[size];
QBENCHMARK {
for (int i = 0; i < size; ++i)
ts[i] = v.value(i);
}
f<T>(ts);
delete[] ts;
}
};
// This subclass implements the use cases using std::vector as efficiently as possible.
template <typename T>
class UseCases_stdvector : public UseCases<T>
{
void insert(int size) override
{
std::vector<T> v;
T t = {};
QBENCHMARK {
for (int i = 0; i < size; ++i)
v.push_back(t);
}
}
void lookup(int size) override
{
std::vector<T> v;
T t = {};
for (int i = 0; i < size; ++i)
v.push_back(t);
T *ts = new T[size];
QBENCHMARK {
for (int i = 0; i < size; ++i)
ts[i] = v[i];
}
f<T>(ts);
delete[] ts;
}
};
struct Large { // A "large" item type
int x[1000];
};
#define LARGE_MAX_SIZE 20000
class tst_vector_vs_std : public QObject
{
Q_OBJECT
public:
tst_vector_vs_std()
{
useCases_QList_int = new UseCases_QList<int>;
useCases_stdvector_int = new UseCases_stdvector<int>;
useCases_QList_Large = new UseCases_QList<Large>;
useCases_stdvector_Large = new UseCases_stdvector<Large>;
}
private:
UseCases<int> *useCases_QList_int;
UseCases<int> *useCases_stdvector_int;
UseCases<Large> *useCases_QList_Large;
UseCases<Large> *useCases_stdvector_Large;
private slots:
void insert_int_data();
void insert_int();
void insert_Large_data();
void insert_Large();
void lookup_int_data();
void lookup_int();
void lookup_Large_data();
void lookup_Large();
};
void tst_vector_vs_std::insert_int_data()
{
QTest::addColumn<bool>("useStd");
QTest::addColumn<int>("size");
for (int size = 10; size < 20000; size += 100) {
const QByteArray sizeString = QByteArray::number(size);
QTest::newRow(QByteArray("std::vector-int--" + sizeString).constData()) << true << size;
QTest::newRow(QByteArray("QList-int--" + sizeString).constData()) << false << size;
}
}
void tst_vector_vs_std::insert_int()
{
QFETCH(bool, useStd);
QFETCH(int, size);
if (useStd)
useCases_stdvector_int->insert(size);
else
useCases_QList_int->insert(size);
}
void tst_vector_vs_std::insert_Large_data()
{
QTest::addColumn<bool>("useStd");
QTest::addColumn<int>("size");
for (int size = 10; size < LARGE_MAX_SIZE; size += 100) {
const QByteArray sizeString = QByteArray::number(size);
QTest::newRow(QByteArray("std::vector-Large--" + sizeString).constData()) << true << size;
QTest::newRow(QByteArray("QList-Large--" + sizeString).constData()) << false << size;
}
}
void tst_vector_vs_std::insert_Large()
{
QFETCH(bool, useStd);
QFETCH(int, size);
if (useStd)
useCases_stdvector_Large->insert(size);
else
useCases_QList_Large->insert(size);
}
void tst_vector_vs_std::lookup_int_data()
{
QTest::addColumn<bool>("useStd");
QTest::addColumn<int>("size");
for (int size = 10; size < 20000; size += 100) {
const QByteArray sizeString = QByteArray::number(size);
QTest::newRow(QByteArray("std::vector-int--" + sizeString).constData()) << true << size;
QTest::newRow(QByteArray("QList-int--" + sizeString).constData()) << false << size;
}
}
void tst_vector_vs_std::lookup_int()
{
QFETCH(bool, useStd);
QFETCH(int, size);
if (useStd)
useCases_stdvector_int->lookup(size);
else
useCases_QList_int->lookup(size);
}
void tst_vector_vs_std::lookup_Large_data()
{
QTest::addColumn<bool>("useStd");
QTest::addColumn<int>("size");
for (int size = 10; size < LARGE_MAX_SIZE; size += 100) {
const QByteArray sizeString = QByteArray::number(size);
QTest::newRow(QByteArray("std::vector-Large--" + sizeString).constData()) << true << size;
QTest::newRow(QByteArray("QList-Large--" + sizeString).constData()) << false << size;
}
}
void tst_vector_vs_std::lookup_Large()
{
QFETCH(bool, useStd);
QFETCH(int, size);
if (useStd)
useCases_stdvector_Large->lookup(size);
else
useCases_QList_Large->lookup(size);
}
QTEST_MAIN(tst_vector_vs_std)
#include "tst_bench_containers_sequential.moc"

View File

@ -0,0 +1,13 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
#####################################################################
## tst_bench_qcontiguouscache Binary:
#####################################################################
qt_internal_add_benchmark(tst_bench_qcontiguouscache
SOURCES
tst_bench_qcontiguouscache.cpp
LIBRARIES
Qt::Test
)

View File

@ -0,0 +1,154 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include <QObject>
#include <QTest>
#include <QCache>
#include <QContiguousCache>
#include <QDebug>
#include <stdio.h>
class tst_QContiguousCache : public QObject
{
Q_OBJECT
public:
tst_QContiguousCache() {}
virtual ~tst_QContiguousCache() {}
private slots:
void asScrollingList();
void cacheBenchmark();
void contiguousCacheBenchmark();
};
void tst_QContiguousCache::asScrollingList()
{
int i;
QContiguousCache<int> c(10);
// Once allocated QContiguousCache should not
// allocate any additional memory for non
// complex data types.
QBENCHMARK {
// simulate scrolling in a list of items;
for (i = 0; i < 10; ++i) {
QCOMPARE(c.available(), 10-i);
c.append(i);
}
QCOMPARE(c.firstIndex(), 0);
QCOMPARE(c.lastIndex(), 9);
QCOMPARE(c.first(), 0);
QCOMPARE(c.last(), 9);
QVERIFY(!c.containsIndex(-1));
QVERIFY(!c.containsIndex(10));
QCOMPARE(c.available(), 0);
for (i = 0; i < 10; ++i) {
QVERIFY(c.containsIndex(i));
QCOMPARE(c.at(i), i);
QCOMPARE(c[i], i);
QCOMPARE(((const QContiguousCache<int>)c)[i], i);
}
for (i = 10; i < 30; ++i)
c.append(i);
QCOMPARE(c.firstIndex(), 20);
QCOMPARE(c.lastIndex(), 29);
QCOMPARE(c.first(), 20);
QCOMPARE(c.last(), 29);
QVERIFY(!c.containsIndex(19));
QVERIFY(!c.containsIndex(30));
QCOMPARE(c.available(), 0);
for (i = 20; i < 30; ++i) {
QVERIFY(c.containsIndex(i));
QCOMPARE(c.at(i), i);
QCOMPARE(c[i], i);
QCOMPARE(((const QContiguousCache<int> )c)[i], i);
}
for (i = 19; i >= 10; --i)
c.prepend(i);
QCOMPARE(c.firstIndex(), 10);
QCOMPARE(c.lastIndex(), 19);
QCOMPARE(c.first(), 10);
QCOMPARE(c.last(), 19);
QVERIFY(!c.containsIndex(9));
QVERIFY(!c.containsIndex(20));
QCOMPARE(c.available(), 0);
for (i = 10; i < 20; ++i) {
QVERIFY(c.containsIndex(i));
QCOMPARE(c.at(i), i);
QCOMPARE(c[i], i);
QCOMPARE(((const QContiguousCache<int> )c)[i], i);
}
for (i = 200; i < 220; ++i)
c.insert(i, i);
QCOMPARE(c.firstIndex(), 210);
QCOMPARE(c.lastIndex(), 219);
QCOMPARE(c.first(), 210);
QCOMPARE(c.last(), 219);
QVERIFY(!c.containsIndex(209));
QVERIFY(!c.containsIndex(300));
QCOMPARE(c.available(), 0);
for (i = 210; i < 220; ++i) {
QVERIFY(c.containsIndex(i));
QCOMPARE(c.at(i), i);
QCOMPARE(c[i], i);
QCOMPARE(((const QContiguousCache<int> )c)[i], i);
}
c.clear(); // needed to reset benchmark
}
// from a specific bug that was encountered. 100 to 299 cached, attempted to cache 250 - 205 via insert, failed.
// bug was that item at 150 would instead be item that should have been inserted at 250
c.setCapacity(200);
for (i = 100; i < 300; ++i)
c.insert(i, i);
for (i = 250; i <= 306; ++i)
c.insert(i, 1000+i);
for (i = 107; i <= 306; ++i) {
QVERIFY(c.containsIndex(i));
QCOMPARE(c.at(i), i < 250 ? i : 1000+i);
}
}
/*
Benchmarks must be near identical in tasks to be fair.
QCache uses pointers to ints as its a requirement of QCache,
whereas QContiguousCache doesn't support pointers (won't free them).
Given the ability to use simple data types is a benefit, its
fair. Although this obviously must take into account we are
testing QContiguousCache use cases here, QCache has its own
areas where it is the more sensible class to use.
*/
void tst_QContiguousCache::cacheBenchmark()
{
QBENCHMARK {
QCache<int, int> cache;
cache.setMaxCost(100);
for (int i = 0; i < 1000; i++)
cache.insert(i, new int(i));
}
}
void tst_QContiguousCache::contiguousCacheBenchmark()
{
QBENCHMARK {
QContiguousCache<int> contiguousCache(100);
for (int i = 0; i < 1000; i++)
contiguousCache.insert(i, i);
}
}
QTEST_MAIN(tst_QContiguousCache)
#include "tst_bench_qcontiguouscache.moc"

View File

@ -0,0 +1,13 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
#####################################################################
## tst_bench_qcryptographichash Binary:
#####################################################################
qt_internal_add_benchmark(tst_bench_qcryptographichash
SOURCES
tst_bench_qcryptographichash.cpp
LIBRARIES
Qt::Test
)

View File

@ -0,0 +1,223 @@
// Copyright (C) 2023 The Qt Company Ltd.
// Copyright (C) 2017 Intel Corporation.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include <QByteArray>
#include <QCryptographicHash>
#include <QFile>
#include <QMetaEnum>
#include <QMessageAuthenticationCode>
#include <QRandomGenerator>
#include <QString>
#include <QTest>
#include <qxpfunctional.h>
#include <numeric>
#include <time.h>
class tst_QCryptographicHash : public QObject
{
Q_OBJECT
QByteArray blockOfData;
using Algorithm = QCryptographicHash::Algorithm;
public:
tst_QCryptographicHash();
private Q_SLOTS:
void hash_data();
void hash();
void addData_data() { hash_data(); }
void addData();
void addDataChunked_data() { hash_data(); }
void addDataChunked();
// QMessageAuthenticationCode:
void hmac_hash_data() { hash_data(); }
void hmac_hash();
void hmac_addData_data() { hash_data(); }
void hmac_addData();
void hmac_setKey_data();
void hmac_setKey();
};
const int MaxBlockSize = 65536;
static void for_each_algorithm(qxp::function_ref<void(QCryptographicHash::Algorithm, const char*) const> f)
{
using A = QCryptographicHash::Algorithm;
static const auto metaEnum = QMetaEnum::fromType<A>();
for (int i = 0, value = metaEnum.value(i); value != -1; value = metaEnum.value(++i))
f(A(value), metaEnum.key(i));
}
tst_QCryptographicHash::tst_QCryptographicHash()
: blockOfData(MaxBlockSize, Qt::Uninitialized)
{
#ifdef Q_OS_UNIX
QFile urandom("/dev/urandom");
if (urandom.open(QIODevice::ReadOnly | QIODevice::Unbuffered)) {
QCOMPARE(urandom.read(blockOfData.data(), blockOfData.size()), qint64(MaxBlockSize));
} else
#endif
{
for (int i = 0; i < MaxBlockSize; ++i)
blockOfData[i] = QRandomGenerator::global()->generate();
}
}
void tst_QCryptographicHash::hash_data()
{
QTest::addColumn<Algorithm>("algo");
QTest::addColumn<QByteArray>("data");
static const int datasizes[] = { 0, 1, 64, 65, 512, 4095, 4096, 4097, 65536 };
for (uint i = 0; i < sizeof(datasizes)/sizeof(datasizes[0]); ++i) {
Q_ASSERT(datasizes[i] < MaxBlockSize);
QByteArray data = QByteArray::fromRawData(blockOfData.constData(), datasizes[i]);
for_each_algorithm([&] (Algorithm algo, const char *name) {
if (algo == Algorithm::NumAlgorithms)
return;
QTest::addRow("%s-%d", name, datasizes[i]) << algo << data;
});
}
}
#define SKIP_IF_NOT_SUPPORTED(algo) do { \
if (!QCryptographicHash::supportsAlgorithm(algo)) \
QSKIP("This algorithm is not supported in this configuration"); \
} while (false) \
/* end */
void tst_QCryptographicHash::hash()
{
QFETCH(const Algorithm, algo);
QFETCH(QByteArray, data);
SKIP_IF_NOT_SUPPORTED(algo);
QBENCHMARK {
[[maybe_unused]]
auto r = QCryptographicHash::hash(data, algo);
}
}
void tst_QCryptographicHash::addData()
{
QFETCH(const Algorithm, algo);
QFETCH(QByteArray, data);
SKIP_IF_NOT_SUPPORTED(algo);
QCryptographicHash hash(algo);
QBENCHMARK {
hash.reset();
hash.addData(data);
[[maybe_unused]]
auto r = hash.resultView();
}
}
void tst_QCryptographicHash::addDataChunked()
{
QFETCH(const Algorithm, algo);
QFETCH(QByteArray, data);
SKIP_IF_NOT_SUPPORTED(algo);
QCryptographicHash hash(algo);
QBENCHMARK {
hash.reset();
// add the data in chunks of 64 bytes
for (int i = 0; i < data.size() / 64; ++i)
hash.addData({data.constData() + 64 * i, 64});
hash.addData({data.constData() + data.size() / 64 * 64, data.size() % 64});
[[maybe_unused]]
auto r = hash.resultView();
}
}
static QByteArray hmacKey() {
static QByteArray key = [] {
QByteArray result(277, Qt::Uninitialized);
std::iota(result.begin(), result.end(), uchar(0)); // uchar so wraps after UCHAR_MAX
return result;
}();
return key;
}
void tst_QCryptographicHash::hmac_hash()
{
QFETCH(const Algorithm, algo);
QFETCH(const QByteArray, data);
SKIP_IF_NOT_SUPPORTED(algo);
const auto key = hmacKey();
QBENCHMARK {
[[maybe_unused]]
auto r = QMessageAuthenticationCode::hash(data, key, algo);
}
}
void tst_QCryptographicHash::hmac_addData()
{
QFETCH(const Algorithm, algo);
QFETCH(const QByteArray, data);
SKIP_IF_NOT_SUPPORTED(algo);
const auto key = hmacKey();
QMessageAuthenticationCode mac(algo, key);
QBENCHMARK {
mac.reset();
mac.addData(data);
[[maybe_unused]]
auto r = mac.result();
}
}
void tst_QCryptographicHash::hmac_setKey_data()
{
QTest::addColumn<Algorithm>("algo");
for_each_algorithm([] (Algorithm algo, const char *name) {
if (algo == Algorithm::NumAlgorithms)
return;
QTest::addRow("%s", name) << algo;
});
}
void tst_QCryptographicHash::hmac_setKey()
{
QFETCH(const Algorithm, algo);
SKIP_IF_NOT_SUPPORTED(algo);
const QByteArrayList keys = [] {
QByteArrayList result;
const auto fullKey = hmacKey();
result.reserve(fullKey.size());
for (auto i = fullKey.size(); i > 0; --i)
result.push_back(fullKey.sliced(i));
return result;
}();
QMessageAuthenticationCode mac(algo);
QBENCHMARK {
for (const auto &key : keys) {
mac.setKey(key);
mac.addData("abc", 3); // avoid lazy setKey()
}
}
}
#undef SKIP_IF_NOT_SUPPORTED
QTEST_APPLESS_MAIN(tst_QCryptographicHash)
#include "tst_bench_qcryptographichash.moc"

View File

@ -0,0 +1,16 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
#####################################################################
## tst_bench_qhash Binary:
#####################################################################
qt_internal_add_benchmark(tst_bench_qhash
SOURCES
tst_bench_qhash.cpp
outofline.cpp
INCLUDE_DIRECTORIES
.
LIBRARIES
Qt::Test
)

View File

@ -0,0 +1,56 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "tst_bench_qhash.h"
QT_BEGIN_NAMESPACE
size_t qHash(const Qt4String &str)
{
qsizetype n = str.size();
const QChar *p = str.unicode();
uint h = 0;
while (n--) {
h = (h << 4) + (*p++).unicode();
h ^= (h & 0xf0000000) >> 23;
h &= 0x0fffffff;
}
return h;
}
size_t qHash(const Qt50String &key, size_t seed)
{
const QChar *p = key.unicode();
qsizetype len = key.size();
size_t h = seed;
for (int i = 0; i < len; ++i)
h = 31 * h + p[i].unicode();
return h;
}
// The Java's hashing algorithm for strings is a variation of D. J. Bernstein
// hashing algorithm appeared here http://cr.yp.to/cdb/cdb.txt
// and informally known as DJB33XX - DJB's 33 Times Xor.
// Java uses DJB31XA, that is, 31 Times Add.
// The original algorithm was a loop around "(h << 5) + h ^ c",
// which is indeed "h * 33 ^ c"; it was then changed to
// "(h << 5) - h ^ c", so "h * 31 ^ c", and the XOR changed to a sum:
// "(h << 5) - h + c", which can save some assembly instructions.
// Still, we can avoid writing the multiplication as "(h << 5) - h"
// -- the compiler will turn it into a shift and an addition anyway
// (for instance, gcc 4.4 does that even at -O0).
size_t qHash(const JavaString &str)
{
const auto *p = reinterpret_cast<const char16_t *>(str.constData());
const qsizetype len = str.size();
uint h = 0;
for (int i = 0; i < len; ++i)
h = 31 * h + p[i];
return h;
}
QT_END_NAMESPACE

View File

@ -0,0 +1,187 @@
.
./corelib.pro
./kernel
./kernel/kernel.pro
./kernel/qobject
./kernel/qobject/main.cpp
./kernel/qobject/object.cpp
./kernel/qobject/object.h
./kernel/qobject/Makefile
./kernel/qobject/qobject.pro
./kernel/qvariant
./kernel/qvariant/tst_qvariant.cpp
./kernel/qvariant/Makefile
./kernel/qvariant/qvariant.pro
./kernel/qtimer_vs_qmetaobject
./kernel/qtimer_vs_qmetaobject/tst_qtimer_vs_qmetaobject.cpp
./kernel/qtimer_vs_qmetaobject/Makefile
./kernel/qtimer_vs_qmetaobject/qtimer_vs_qmetaobject.pro
./kernel/.pch
./kernel/.pch/debug-shared
./kernel/qmetaobject
./kernel/qmetaobject/main.cpp
./kernel/qmetaobject/qmetaobject.pro
./kernel/qmetaobject/Makefile
./kernel/Makefile
./kernel/.obj
./kernel/.obj/debug-shared
./kernel/events
./kernel/events/events.pro
./kernel/events/main.cpp
./kernel/events/Makefile
./kernel/qmetatype
./kernel/qmetatype/qmetatype.pro
./kernel/qmetatype/Makefile
./kernel/qmetatype/tst_qmetatype.cpp
./.pch
./.pch/debug-shared
./text
./text/text.pro
./text/qregexp
./text/qregexp/qregexp.qrc
./text/qregexp/main.cpp
./text/qregexp/Makefile
./text/qregexp/qregexp.pro
./text/qstringbuilder
./text/qstringbuilder/main.cpp
./text/qstringbuilder/Makefile
./text/qstringbuilder/qstringbuilder.pro
./text/qstring
./text/qstring/generatelist.pl
./text/qstring/data.h
./text/qstring/qstring.pro
./text/qstring/main.cpp
./text/qstring/data.cpp
./text/qstring/Makefile
./text/qstring/utf-8.txt
./text/qstringlist
./text/qstringlist/qstringlist.pro
./text/qstringlist/main.cpp
./text/qstringlist/.gitignore
./text/qstringlist/Makefile
./text/qbytearray
./text/qbytearray/qbytearray.pro
./text/qbytearray/main.cpp
./text/qbytearray/Makefile
./text/.pch
./text/.pch/debug-shared
./tools
./tools/tools.pro
./tools/qvector
./tools/qvector/tst_vector
./tools/qvector/.pch
./tools/qvector/.pch/debug-shared
./tools/qvector/qrawvector.h
./tools/qvector/main.cpp
./tools/qvector/Makefile
./tools/qvector/.moc
./tools/qvector/.moc/release-shared
./tools/qvector/.moc/release-shared/main.moc
./tools/qvector/.obj
./tools/qvector/.obj/release-shared
./tools/qvector/.obj/release-shared/outofline.o
./tools/qvector/.obj/release-shared/main.o
./tools/qvector/outofline.cpp
./tools/qvector/qvector.pro
./tools/.pch
./tools/.pch/debug-shared
./tools/containers-sequential
./tools/containers-sequential/containers-sequential.pro
./tools/containers-sequential/main.cpp
./tools/containers-sequential/Makefile
./tools/containers-associative
./tools/containers-associative/containers-associative.pro
./tools/containers-associative/main.cpp
./tools/containers-associative/Makefile
./tools/qrect
./tools/qrect/main.cpp
./tools/qrect/Makefile
./tools/qrect/qrect.pro
./tools/Makefile
./tools/qhash
./tools/qhash/data.txt
./tools/qhash/qhash_string.cpp
./tools/qhash/.qhash_string.cpp.swp
./tools/qhash/qhash.pro
./tools/qhash/outofline.cpp
./tools/.obj
./tools/.obj/debug-shared
./Makefile
./.obj
./.obj/debug-shared
./plugin
./plugin/plugin.pro
./plugin/.pch
./plugin/.pch/debug-shared
./plugin/Makefile
./plugin/.obj
./plugin/.obj/debug-shared
./plugin/quuid
./plugin/quuid/tst_quuid.cpp
./plugin/quuid/quuid.pro
./plugin/quuid/Makefile
./io
./io/qtemporaryfile
./io/qtemporaryfile/qtemporaryfile.pro
./io/qtemporaryfile/main.cpp
./io/qtemporaryfile/Makefile
./io/qiodevice
./io/qiodevice/qiodevice.pro
./io/qiodevice/main.cpp
./io/qiodevice/Makefile
./io/qurl
./io/qurl/main.cpp
./io/qurl/Makefile
./io/qurl/qurl.pro
./io/qdir
./io/qdir/.pch
./io/qdir/.pch/debug-shared
./io/qdir/qdir.pro
./io/qdir/tree
./io/qdir/tree/bench_qdir_tree.qrc
./io/qdir/tree/tree.pro
./io/qdir/tree/4.6.0-list.txt
./io/qdir/tree/Makefile
./io/qdir/tree/bench_qdir_tree.cpp
./io/qdir/Makefile
./io/qdir/.obj
./io/qdir/.obj/debug-shared
./io/qdir/10000
./io/qdir/10000/10000.pro
./io/qdir/10000/bench_qdir_10000.cpp
./io/qdir/10000/Makefile
./io/.pch
./io/.pch/debug-shared
./io/qfile
./io/qfile/qfile.pro
./io/qfile/main.cpp
./io/qfile/Makefile
./io/io.pro
./io/qfileinfo
./io/qfileinfo/qfileinfo.pro
./io/qfileinfo/main.cpp
./io/qfileinfo/Makefile
./io/qdiriterator
./io/qdiriterator/qfilesystemiterator.h
./io/qdiriterator/main.cpp
./io/qdiriterator/Makefile
./io/qdiriterator/qfilesystemiterator.cpp
./io/qdiriterator/qdiriterator.pro
./io/Makefile
./io/.obj
./io/.obj/debug-shared
./thread
./thread/qmutex
./thread/qmutex/tst_qmutex.cpp
./thread/qmutex/Makefile
./thread/qmutex/qmutex.pro
./thread/qthreadstorage
./thread/qthreadstorage/qthreadstorage.pro
./thread/qthreadstorage/Makefile
./thread/qthreadstorage/tst_qthreadstorage.cpp
./thread/.pch
./thread/.pch/debug-shared
./thread/Makefile
./thread/.obj
./thread/.obj/debug-shared
./thread/thread.pro

View File

@ -0,0 +1,149 @@
// Copyright (C) 2016 The Qt Company Ltd.
// Copyright (C) 2016 Intel Corporation.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "tst_bench_qhash.h"
#include <QFile>
#include <QHash>
#include <QString>
#include <QStringList>
#include <QUuid>
#include <QTest>
class tst_QHash : public QObject
{
Q_OBJECT
private slots:
void initTestCase();
void qhash_current_data() { data(); }
void qhash_current() { qhash_template<QString>(); }
void qhash_qt50_data() { data(); }
void qhash_qt50() { qhash_template<Qt50String>(); }
void qhash_qt4_data() { data(); }
void qhash_qt4() { qhash_template<Qt4String>(); }
void qhash_javaString_data() { data(); }
void qhash_javaString() { qhash_template<JavaString>(); }
void hashing_current_data() { data(); }
void hashing_current() { hashing_template<QString>(); }
void hashing_qt50_data() { data(); }
void hashing_qt50() { hashing_template<Qt50String>(); }
void hashing_qt4_data() { data(); }
void hashing_qt4() { hashing_template<Qt4String>(); }
void hashing_javaString_data() { data(); }
void hashing_javaString() { hashing_template<JavaString>(); }
private:
void data();
template <typename String> void qhash_template();
template <typename String> void hashing_template();
QStringList smallFilePaths;
QStringList uuids;
QStringList dict;
QStringList numbers;
};
///////////////////// QHash /////////////////////
#include <QDebug>
void tst_QHash::initTestCase()
{
// small list of strings (that happen to look like file paths produced long
// ago by cd ../.. && find . -print, but that's irrelevant).
QFile smallPathsData(QFINDTESTDATA("paths_small_data.txt"));
QVERIFY(smallPathsData.open(QIODevice::ReadOnly));
smallFilePaths = QString::fromLatin1(smallPathsData.readAll()).split(QLatin1Char('\n'));
QVERIFY(!smallFilePaths.isEmpty());
// list of UUIDs
// guaranteed to be completely random, generated by http://xkcd.com/221/
QUuid ns = QUuid("{f43d2ef3-2fe9-4563-a6f5-5a0100c2d699}");
uuids.reserve(smallFilePaths.size());
foreach (const QString &path, smallFilePaths)
uuids.append(QUuid::createUuidV5(ns, path).toString());
// lots of strings with alphabetical characters, vaguely reminiscent of
// a dictionary.
//
// this programmatically generates a series like:
// AAAAAA
// AAAAAB
// AAAAAC
// ...
// AAAAAZ
// AAAABZ
// ...
// AAAAZZ
// AAABZZ
QByteArray id("AAAAAAA");
if (dict.isEmpty()) {
for (int i = id.size() - 1; i > 0;) {
dict.append(id);
char c = id.at(i);
id[i] = ++c;
if (c == 'Z') {
// wrap to next digit
i--;
id[i] = 'A';
}
}
}
// string versions of numbers.
for (int i = 5000000; i < 5005001; ++i)
numbers.append(QString::number(i));
}
void tst_QHash::data()
{
QTest::addColumn<QStringList>("items");
QTest::newRow("paths-small") << smallFilePaths;
QTest::newRow("uuids-list") << uuids;
QTest::newRow("dictionary") << dict;
QTest::newRow("numbers") << numbers;
}
template <typename String> void tst_QHash::qhash_template()
{
QFETCH(QStringList, items);
QHash<String, int> hash;
QList<String> realitems;
foreach (const QString &s, items)
realitems.append(s);
QBENCHMARK {
for (int i = 0, n = realitems.size(); i != n; ++i) {
hash[realitems.at(i)] = i;
}
}
}
template <typename String> void tst_QHash::hashing_template()
{
// just the hashing function
QFETCH(QStringList, items);
QList<String> realitems;
realitems.reserve(items.size());
foreach (const QString &s, items)
realitems.append(s);
QBENCHMARK {
for (int i = 0, n = realitems.size(); i != n; ++i)
(void)qHash(realitems.at(i));
}
}
QTEST_MAIN(tst_QHash)
#include "tst_bench_qhash.moc"

View File

@ -0,0 +1,36 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include <QString>
struct Qt4String : QString
{
Qt4String() {}
Qt4String(const QString &s) : QString(s) {}
};
QT_BEGIN_NAMESPACE
size_t qHash(const Qt4String &);
QT_END_NAMESPACE
struct Qt50String : QString
{
Qt50String() {}
Qt50String(const QString &s) : QString(s) {}
};
QT_BEGIN_NAMESPACE
size_t qHash(const Qt50String &, size_t seed = 0);
QT_END_NAMESPACE
struct JavaString : QString
{
JavaString() {}
JavaString(const QString &s) : QString(s) {}
};
QT_BEGIN_NAMESPACE
size_t qHash(const JavaString &);
QT_END_NAMESPACE

View File

@ -0,0 +1,13 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
#####################################################################
## tst_bench_qlist Binary:
#####################################################################
qt_internal_add_benchmark(tst_bench_qlist
SOURCES
tst_bench_qlist.cpp
LIBRARIES
Qt::Test
)

View File

@ -0,0 +1,410 @@
// Copyright (C) 2021 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include <QList>
#include <QTest>
#include <utility>
static const int N = 1000;
struct MyBase
{
MyBase(int i_) : i(i_) { }
MyBase(const MyBase &other) : i(other.i) { }
MyBase &operator=(const MyBase &other)
{
i = other.i;
return *this;
}
bool operator==(const MyBase &other) const
{ return i == other.i; }
protected:
int i;
};
struct MyPrimitive : public MyBase
{
MyPrimitive(int i_ = -1) : MyBase(i_) { }
MyPrimitive(const MyPrimitive &other) : MyBase(other) { }
MyPrimitive &operator=(const MyPrimitive &other)
{
MyBase::operator=(other);
return *this;
}
};
struct MyMovable : public MyBase
{
MyMovable(int i_ = -1) : MyBase(i_) {}
};
struct MyComplex : public MyBase
{
MyComplex(int i_ = -1) : MyBase(i_) {}
};
QT_BEGIN_NAMESPACE
Q_DECLARE_TYPEINFO(MyPrimitive, Q_PRIMITIVE_TYPE);
Q_DECLARE_TYPEINFO(MyMovable, Q_RELOCATABLE_TYPE);
Q_DECLARE_TYPEINFO(MyComplex, Q_COMPLEX_TYPE);
QT_END_NAMESPACE
class tst_QList: public QObject
{
Q_OBJECT
const int million = 1000000;
private Q_SLOTS:
void removeAll_primitive_data();
void removeAll_primitive() { removeAll_impl<MyPrimitive>(); }
void removeAll_movable_data() { removeAll_primitive_data(); }
void removeAll_movable() { removeAll_impl<MyMovable>(); }
void removeAll_complex_data() { removeAll_primitive_data(); }
void removeAll_complex() { removeAll_impl<MyComplex>(); }
// append 1 element:
void appendOne_int_data() const { commonBenchmark_data<int>(); }
void appendOne_primitive_data() const { commonBenchmark_data<MyPrimitive>(); }
void appendOne_movable_data() const { commonBenchmark_data<MyMovable>(); }
void appendOne_complex_data() const { commonBenchmark_data<MyComplex>(); }
void appendOne_QString_data() const { commonBenchmark_data<QString>(); }
void appendOne_int() const { appendOne_impl<QList, int>(); } // QTBUG-87330
void appendOne_primitive() const { appendOne_impl<QList, MyPrimitive>(); }
void appendOne_movable() const { appendOne_impl<QList, MyMovable>(); }
void appendOne_complex() const { appendOne_impl<QList, MyComplex>(); }
void appendOne_QString() const { appendOne_impl<QList, QString>(); }
// prepend 1 element:
void prependOne_int_data() const { commonBenchmark_data<int>(); }
void prependOne_primitive_data() const { commonBenchmark_data<MyPrimitive>(); }
void prependOne_movable_data() const { commonBenchmark_data<MyMovable>(); }
void prependOne_complex_data() const { commonBenchmark_data<MyComplex>(); }
void prependOne_QString_data() const { commonBenchmark_data<QString>(); }
void prependOne_int() const { prependOne_impl<QList, int>(); }
void prependOne_primitive() const { prependOne_impl<QList, MyPrimitive>(); }
void prependOne_movable() const { prependOne_impl<QList, MyMovable>(); }
void prependOne_complex() const { prependOne_impl<QList, MyComplex>(); }
void prependOne_QString() const { prependOne_impl<QList, QString>(); }
// insert in middle 1 element (quadratic, slow):
void midInsertOne_int_data() const { commonBenchmark_data<int>(million); }
void midInsertOne_primitive_data() const { commonBenchmark_data<MyPrimitive>(million); }
void midInsertOne_movable_data() const { commonBenchmark_data<MyMovable>(million); }
void midInsertOne_complex_data() const { commonBenchmark_data<MyComplex>(million / 10); }
void midInsertOne_QString_data() const { commonBenchmark_data<QString>(million / 10); }
void midInsertOne_int() const { midInsertOne_impl<QList, int>(); }
void midInsertOne_primitive() const { midInsertOne_impl<QList, MyPrimitive>(); }
void midInsertOne_movable() const { midInsertOne_impl<QList, MyMovable>(); }
void midInsertOne_complex() const { midInsertOne_impl<QList, MyComplex>(); }
void midInsertOne_QString() const { midInsertOne_impl<QList, QString>(); }
// append/prepend 1 element - hard times for branch predictor:
void appendPrependOne_int_data() const { commonBenchmark_data<int>(); }
void appendPrependOne_primitive_data() const { commonBenchmark_data<MyPrimitive>(); }
void appendPrependOne_movable_data() const { commonBenchmark_data<MyMovable>(); }
void appendPrependOne_complex_data() const { commonBenchmark_data<MyComplex>(); }
void appendPrependOne_QString_data() const { commonBenchmark_data<QString>(); }
void appendPrependOne_int() const { appendPrependOne_impl<QList, int>(); }
void appendPrependOne_primitive() const { appendPrependOne_impl<QList, MyPrimitive>(); }
void appendPrependOne_movable() const { appendPrependOne_impl<QList, MyMovable>(); }
void appendPrependOne_complex() const { appendPrependOne_impl<QList, MyComplex>(); }
void appendPrependOne_QString() const { appendPrependOne_impl<QList, QString>(); }
// prepend half elements, then appen another half:
void prependAppendHalvesOne_int_data() const { commonBenchmark_data<int>(); }
void prependAppendHalvesOne_primitive_data() const { commonBenchmark_data<MyPrimitive>(); }
void prependAppendHalvesOne_movable_data() const { commonBenchmark_data<MyMovable>(); }
void prependAppendHalvesOne_complex_data() const { commonBenchmark_data<MyComplex>(); }
void prependAppendHalvesOne_QString_data() const { commonBenchmark_data<QString>(); }
void prependAppendHalvesOne_int() const { prependAppendHalvesOne_impl<QList, int>(); }
void prependAppendHalvesOne_primitive() const
{
prependAppendHalvesOne_impl<QList, MyPrimitive>();
}
void prependAppendHalvesOne_movable() const { prependAppendHalvesOne_impl<QList, MyMovable>(); }
void prependAppendHalvesOne_complex() const { prependAppendHalvesOne_impl<QList, MyComplex>(); }
void prependAppendHalvesOne_QString() const { prependAppendHalvesOne_impl<QList, QString>(); }
// emplace in middle 1 element (quadratic, slow):
void midEmplaceOne_int_data() const { commonBenchmark_data<int>(million); }
void midEmplaceOne_primitive_data() const { commonBenchmark_data<MyPrimitive>(million); }
void midEmplaceOne_movable_data() const { commonBenchmark_data<MyMovable>(million); }
void midEmplaceOne_complex_data() const { commonBenchmark_data<MyComplex>(million / 10); }
void midEmplaceOne_QString_data() const { commonBenchmark_data<QString>(million / 10); }
void midEmplaceOne_int() const { midEmplaceOne_impl<QList, int>(); }
void midEmplaceOne_primitive() const { midEmplaceOne_impl<QList, MyPrimitive>(); }
void midEmplaceOne_movable() const { midEmplaceOne_impl<QList, MyMovable>(); }
void midEmplaceOne_complex() const { midEmplaceOne_impl<QList, MyComplex>(); }
void midEmplaceOne_QString() const { midEmplaceOne_impl<QList, QString>(); }
// remove from beginning in a general way
void removeFirstGeneral_int_data() const { commonBenchmark_data<int>(); }
void removeFirstGeneral_primitive_data() const { commonBenchmark_data<MyPrimitive>(); }
void removeFirstGeneral_movable_data() const { commonBenchmark_data<MyMovable>(); }
void removeFirstGeneral_complex_data() const { commonBenchmark_data<MyComplex>(); }
void removeFirstGeneral_QString_data() const { commonBenchmark_data<QString>(); }
void removeFirstGeneral_int() const { removeFirstGeneral_impl<QList, int>(); }
void removeFirstGeneral_primitive() const { removeFirstGeneral_impl<QList, MyPrimitive>(); }
void removeFirstGeneral_movable() const { removeFirstGeneral_impl<QList, MyMovable>(); }
void removeFirstGeneral_complex() const { removeFirstGeneral_impl<QList, MyComplex>(); }
void removeFirstGeneral_QString() const { removeFirstGeneral_impl<QList, QString>(); }
// remove from beginning in a special way (using fast part of QList::removeFirst())
void removeFirstSpecial_int_data() const { commonBenchmark_data<int>(); }
void removeFirstSpecial_primitive_data() const { commonBenchmark_data<MyPrimitive>(); }
void removeFirstSpecial_movable_data() const { commonBenchmark_data<MyMovable>(); }
void removeFirstSpecial_complex_data() const { commonBenchmark_data<MyComplex>(); }
void removeFirstSpecial_QString_data() const { commonBenchmark_data<QString>(); }
void removeFirstSpecial_int() const { removeFirstSpecial_impl<QList, int>(); }
void removeFirstSpecial_primitive() const { removeFirstSpecial_impl<QList, MyPrimitive>(); }
void removeFirstSpecial_movable() const { removeFirstSpecial_impl<QList, MyMovable>(); }
void removeFirstSpecial_complex() const { removeFirstSpecial_impl<QList, MyComplex>(); }
void removeFirstSpecial_QString() const { removeFirstSpecial_impl<QList, QString>(); }
private:
template <class T>
void removeAll_impl() const;
template<typename>
void commonBenchmark_data(int max = 200000000) const;
template<template<typename> typename, typename>
void appendOne_impl() const;
template<template<typename> typename, typename>
void prependOne_impl() const;
template<template<typename> typename, typename>
void midInsertOne_impl() const;
template<template<typename> typename, typename>
void appendPrependOne_impl() const;
template<template<typename> typename, typename>
void prependAppendHalvesOne_impl() const;
template<template<typename> typename, typename>
void midEmplaceOne_impl() const;
template<template<typename> typename, typename>
void removeFirstGeneral_impl() const;
template<template<typename> typename, typename>
void removeFirstSpecial_impl() const;
};
template <class T>
void tst_QList::removeAll_impl() const
{
QFETCH(QList<int>, i10);
QFETCH(int, itemsToRemove);
constexpr int valueToRemove = 5;
QList<T> list;
for (int i = 0; i < 10 * N; ++i) {
T t(i10.at(i % 10));
list.append(t);
}
T t(valueToRemove);
qsizetype removedCount = 0; // make compiler happy by setting to 0
QList<T> l;
QBENCHMARK {
l = list;
removedCount = l.removeAll(t);
}
QCOMPARE(removedCount, itemsToRemove * N);
QCOMPARE(l.size() + removedCount, list.size());
QVERIFY(!l.contains(valueToRemove));
}
void tst_QList::removeAll_primitive_data()
{
qRegisterMetaType<QList<int> >();
QTest::addColumn<QList<int> >("i10");
QTest::addColumn<int>("itemsToRemove");
QTest::newRow("0%") << QList<int>(10, 0) << 0;
QTest::newRow("10%") << (QList<int>() << 0 << 0 << 0 << 0 << 5 << 0 << 0 << 0 << 0 << 0) << 1;
QTest::newRow("90%") << (QList<int>() << 5 << 5 << 5 << 5 << 0 << 5 << 5 << 5 << 5 << 5) << 9;
QTest::newRow("100%") << QList<int>(10, 5) << 10;
}
template<typename T>
void tst_QList::commonBenchmark_data(int max) const
{
QTest::addColumn<int>("elemCount");
const auto addRow = [](int count, const char *text) { QTest::newRow(text) << count; };
const auto p = [](int i, const char *text) { return std::make_pair(i, text); };
// cap at 20m elements to allow 5.15/6.0 coverage to be the same
for (auto pair : { p(100, "100"), p(1000, "1k"), p(10000, "10k"), p(100000, "100k"),
p(1000000, "1m"), p(10000000, "10m"), p(20000000, "20m") }) {
if (pair.first <= max)
addRow(pair.first, pair.second);
}
}
template<template<typename> typename Container, typename T>
void tst_QList::appendOne_impl() const
{
QFETCH(int, elemCount);
constexpr auto getValue = []() { return T {}; };
QBENCHMARK {
Container<T> container;
auto lvalue = getValue();
for (int i = 0; i < elemCount; ++i) {
container.append(lvalue);
}
}
}
template<template<typename> typename Container, typename T>
void tst_QList::prependOne_impl() const
{
QFETCH(int, elemCount);
constexpr auto getValue = []() { return T {}; };
QBENCHMARK {
Container<T> container;
auto lvalue = getValue();
for (int i = 0; i < elemCount; ++i) {
container.prepend(lvalue);
}
}
}
template<template<typename> typename Container, typename T>
void tst_QList::midInsertOne_impl() const
{
QFETCH(int, elemCount);
constexpr auto getValue = []() { return T {}; };
QBENCHMARK {
Container<T> container;
auto lvalue = getValue();
for (int i = 0; i < elemCount; ++i) {
const int remainder = i % 2;
// use insert(i, n, t) as insert(i, t) calls emplace (implementation
// detail)
container.insert(container.size() / 2 + remainder, 1, lvalue);
}
}
}
template<template<typename> typename Container, typename T>
void tst_QList::appendPrependOne_impl() const
{
QFETCH(int, elemCount);
constexpr auto getValue = []() { return T {}; };
QBENCHMARK {
Container<T> container;
auto lvalue = getValue();
for (int i = 0; i < elemCount; ++i) {
if (i % 2 == 0) {
container.append(lvalue);
} else {
container.prepend(lvalue);
}
}
}
}
template<template<typename> typename Container, typename T>
void tst_QList::prependAppendHalvesOne_impl() const
{
QFETCH(int, elemCount);
constexpr auto getValue = []() { return T {}; };
QBENCHMARK {
Container<T> container;
auto lvalue = getValue();
for (int i = 0; i < elemCount / 2; ++i) {
container.prepend(lvalue);
}
for (int i = elemCount / 2; i < elemCount; ++i) {
container.append(lvalue);
}
}
}
template<template<typename> typename Container, typename T>
void tst_QList::midEmplaceOne_impl() const
{
QFETCH(int, elemCount);
constexpr auto getValue = []() { return T {}; };
QBENCHMARK {
Container<T> container;
auto lvalue = getValue();
for (int i = 0; i < elemCount; ++i) {
const int remainder = i % 2;
container.emplace(container.size() / 2 + remainder, lvalue);
}
}
}
template<template<typename> typename Container, typename T>
void tst_QList::removeFirstGeneral_impl() const
{
QFETCH(int, elemCount);
constexpr auto getValue = []() { return T {}; };
QBENCHMARK {
Container<T> container(elemCount, getValue());
for (int i = 0; i < elemCount - 1; ++i) {
container.remove(0, 1);
}
}
}
template<template<typename> typename Container, typename T>
void tst_QList::removeFirstSpecial_impl() const
{
QFETCH(int, elemCount);
constexpr auto getValue = []() { return T {}; };
QBENCHMARK {
Container<T> container(elemCount, getValue());
for (int i = 0; i < elemCount; ++i) {
container.removeFirst();
}
}
}
QTEST_APPLESS_MAIN(tst_QList)
#include "tst_bench_qlist.moc"

View File

@ -0,0 +1,15 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
#####################################################################
## tst_bench_qmap Binary:
#####################################################################
qt_internal_add_benchmark(tst_bench_qmap
SOURCES
tst_bench_qmap.cpp
INCLUDE_DIRECTORIES
.
LIBRARIES
Qt::Test
)

View File

@ -0,0 +1,304 @@
// Copyright (C) 2021 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include <QFile>
#include <QMap>
#include <QString>
#include <QTest>
#include <qdebug.h>
class tst_QMap : public QObject
{
Q_OBJECT
private slots:
void insertion_int_int();
void insertion_int_string();
void insertion_string_int();
void lookup_int_int();
void lookup_int_string();
void lookup_string_int();
void iteration();
void toStdMap();
void iterator_begin();
void ctorStdMap();
void insertion_int_intx();
void insertion_int_int_with_hint1();
void insertion_int_int2();
void insertion_int_int_with_hint2();
void insertion_string_int2();
void insertion_string_int2_hint();
void insertMap();
private:
QStringList helloEachWorld(int count);
};
QStringList tst_QMap::helloEachWorld(int count)
{
QStringList result;
result.reserve(count);
result << QStringLiteral("Hello World"); // at index 0, not used
char16_t name[] = u"Hello World";
QStringView str(name);
for (int i = 1; i < count; ++i) {
auto p = name + 6; // In the gap between words.
for (const auto ch : QChar::fromUcs4(i))
p++[0] = ch;
result << str.toString();
}
return result;
}
constexpr int huge = 100000; // one hundred thousand; simple integral data tests
// Sum of i with 0 <= i < huge; overflows, but that's OK as long as it's unsigned:
constexpr uint hugeSum = (uint(huge) / 2) * uint(huge - 1);
constexpr int bigish = 5000; // five thousand; tests using XString's expensive <
void tst_QMap::insertion_int_int()
{
QMap<int, int> map;
QBENCHMARK {
for (int i = 0; i < huge; ++i)
map.insert(i, i);
}
QCOMPARE(map.size(), qsizetype(huge));
}
void tst_QMap::insertion_int_intx()
{
// This is the same test - but executed later.
// The results in the beginning of the test seems to be a somewhat inaccurate.
QMap<int, int> map;
QBENCHMARK {
for (int i = 0; i < huge; ++i)
map.insert(i, i);
}
QCOMPARE(map.size(), qsizetype(huge));
}
void tst_QMap::insertion_int_int_with_hint1()
{
QMap<int, int> map;
QBENCHMARK {
for (int i = 0; i < huge; ++i)
map.insert(map.constEnd(), i, i);
}
QCOMPARE(map.size(), qsizetype(huge));
}
void tst_QMap::insertion_int_int2()
{
QMap<int, int> map;
QBENCHMARK {
for (int i = huge; i >= 0; --i)
map.insert(i, i);
}
QCOMPARE(map.size(), qsizetype(huge) + 1);
}
void tst_QMap::insertion_int_int_with_hint2()
{
QMap<int, int> map;
QBENCHMARK {
for (int i = huge; i >= 0; --i)
map.insert(map.constBegin(), i, i);
}
QCOMPARE(map.size(), qsizetype(huge) + 1);
}
void tst_QMap::insertion_int_string()
{
QMap<int, QString> map;
QString str("Hello World");
QBENCHMARK {
for (int i = 0; i < huge; ++i)
map.insert(i, str);
}
QCOMPARE(map.size(), qsizetype(huge));
}
void tst_QMap::insertion_string_int()
{
QMap<QString, int> map;
const QStringList names = helloEachWorld(huge);
QCOMPARE(names.size(), qsizetype(huge));
QBENCHMARK {
for (int i = 1; i < huge; ++i)
map.insert(names.at(i), i);
}
QCOMPARE(map.size() + 1, qsizetype(huge));
}
void tst_QMap::lookup_int_int()
{
QMap<int, int> map;
for (int i = 0; i < huge; ++i)
map.insert(i, i);
QCOMPARE(map.size(), qsizetype(huge));
uint sum = 0, count = 0;
QBENCHMARK {
for (int i = 0; i < huge; ++i)
sum += map.value(i);
++count;
}
QCOMPARE(sum, hugeSum * count);
}
void tst_QMap::lookup_int_string()
{
QMap<int, QString> map;
QString str("Hello World");
for (int i = 0; i < huge; ++i)
map.insert(i, str);
QCOMPARE(map.size(), qsizetype(huge));
QBENCHMARK {
for (int i = 0; i < huge; ++i)
str = map.value(i);
}
}
void tst_QMap::lookup_string_int()
{
QMap<QString, int> map;
const QStringList names = helloEachWorld(huge);
for (int i = 1; i < huge; ++i)
map.insert(names.at(i), i);
QCOMPARE(map.size() + 1, qsizetype(huge));
uint sum = 0, count = 0;
QBENCHMARK {
for (int i = 1; i < huge; ++i)
sum += map.value(names.at(i));
++count;
}
QCOMPARE(sum, hugeSum * count);
}
// iteration speed doesn't depend on the type of the map.
void tst_QMap::iteration()
{
QMap<int, int> map;
for (int i = 0; i < huge; ++i)
map.insert(i, i);
QCOMPARE(map.size(), qsizetype(huge));
uint sum = 0, count = 0;
QBENCHMARK {
for (int i = 0; i < 100; ++i) {
QMap<int, int>::const_iterator it = map.constBegin();
QMap<int, int>::const_iterator end = map.constEnd();
while (it != end) {
sum += *it;
++it;
}
}
++count;
}
QCOMPARE(sum, hugeSum * 100u * count);
}
void tst_QMap::toStdMap()
{
QMap<int, int> map;
for (int i = 0; i < huge; ++i)
map.insert(i, i);
QCOMPARE(map.size(), qsizetype(huge));
QBENCHMARK {
std::map<int, int> n = map.toStdMap();
n.begin();
}
}
void tst_QMap::iterator_begin()
{
QMap<int, int> map;
for (int i = 0; i < huge; ++i)
map.insert(i, i);
QCOMPARE(map.size(), qsizetype(huge));
QBENCHMARK {
for (int i = 0; i < huge; ++i) {
QMap<int, int>::const_iterator it = map.constBegin();
QMap<int, int>::const_iterator end = map.constEnd();
if (it == end) // same as if (false)
++it;
}
}
}
void tst_QMap::ctorStdMap()
{
std::map<int, int> map;
for (int i = 0; i < huge; ++i)
map.insert(std::pair<int, int>(i, i));
QCOMPARE(map.size(), size_t(huge));
QBENCHMARK {
QMap<int, int> qmap(map);
qmap.constBegin();
}
}
class XString : public QString
{
public:
bool operator < (const XString& x) const // an expensive operator <
{
return toInt() < x.toInt();
}
};
void tst_QMap::insertion_string_int2()
{
QMap<XString, int> map;
QBENCHMARK {
for (int i = 1; i < bigish; ++i) {
XString str;
str.setNum(i);
map.insert(str, i);
}
}
QCOMPARE(map.size() + 1, qsizetype(bigish));
}
void tst_QMap::insertion_string_int2_hint()
{
QMap<XString, int> map;
QBENCHMARK {
for (int i = 1; i < bigish; ++i) {
XString str;
str.setNum(i);
map.insert(map.end(), str, i);
}
}
QCOMPARE(map.size() + 1, qsizetype(bigish));
}
void tst_QMap::insertMap()
{
QMap<int, int> map;
for (int i = 0; i < huge; ++i)
map.insert(i * 4, 0);
QMap<int, int> map2;
for (int i = 0; i < huge / 2; ++i)
map2.insert(i * 7, 0);
QBENCHMARK_ONCE {
map.insert(map2);
}
}
QTEST_MAIN(tst_QMap)
#include "tst_bench_qmap.moc"

View File

@ -0,0 +1,13 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
#####################################################################
## tst_bench_qrect Binary:
#####################################################################
qt_internal_add_benchmark(tst_bench_qrect
SOURCES
tst_bench_qrect.cpp
LIBRARIES
Qt::Test
)

View File

@ -0,0 +1,291 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
// This file contains benchmarks for QRect/QRectF functions.
#include <QDebug>
#include <qtest.h>
class tst_QRect : public QObject
{
Q_OBJECT
private slots:
// QRect functions:
void contains_point_data();
void contains_point();
void contains_rect_data();
void contains_rect();
void intersects_data();
void intersects();
void intersected_data();
void intersected();
void united_data();
void united();
// QRectF functions:
void contains_point_f_data();
void contains_point_f();
void contains_rect_f_data();
void contains_rect_f();
void intersects_f_data();
void intersects_f();
void intersected_f_data();
void intersected_f();
void united_f_data();
void united_f();
};
struct RectRectCombination
{
QString tag;
qreal x1, y1, w1, h1, x2, y2, w2, h2;
RectRectCombination(
const QString &tag,
const qreal x1, const qreal y1, const qreal w1, const qreal h1,
const qreal x2, const qreal y2, const qreal w2, const qreal h2)
: tag(tag), x1(x1), y1(y1), w1(w1), h1(h1), x2(x2), y2(y2), w2(w2), h2(h2) {}
};
static QList<RectRectCombination> createRectRectCombinations()
{
QList<RectRectCombination> result;
result << RectRectCombination("null", 0, 0, 0, 0, 0, 0, 0, 0);
result << RectRectCombination("null1", 0, 0, 0, 0, 0, 0, 10, 10);
result << RectRectCombination("null2", 0, 0, 10, 10, 0, 0, 0, 0);
result << RectRectCombination("miss", 0, 0, 10, 10, 11, 11, 10, 10);
result << RectRectCombination("intersect", 0, 0, 10, 10, 5, 5, 10, 10);
result << RectRectCombination("contain1", 0, 0, 10, 10, 1, 1, 8, 8);
result << RectRectCombination("contain2", 1, 1, 8, 8, 0, 0, 10, 10);
result << RectRectCombination("miss_flip1", 9, 9, -10, -10, 11, 11, 10, 10);
result << RectRectCombination("intersect_flip1", 9, 9, -10, -10, 5, 5, 10, 10);
result << RectRectCombination("contain1_flip1", 9, 9, -10, -10, 1, 1, 8, 8);
result << RectRectCombination("contain2_flip1", 8, 8, -8, -8, 0, 0, 10, 10);
result << RectRectCombination("miss_flip2", 0, 0, 10, 10, 20, 20, -10, -10);
result << RectRectCombination("intersect_flip2", 0, 0, 10, 10, 14, 14, -10, -10);
result << RectRectCombination("contain1_flip2", 0, 0, 10, 10, 8, 8, -8, -8);
result << RectRectCombination("contain2_flip2", 1, 1, 8, 8, 9, 9, -10, -10);
return result;
}
static void addRectRectData(bool includeProperArg = false)
{
QTest::addColumn<QRectF>("rf1");
QTest::addColumn<QRectF>("rf2");
if (includeProperArg)
QTest::addColumn<bool>("proper");
for (int i = 0; i < (includeProperArg ? 2 : 1); ++i) {
QList<RectRectCombination> combinations = createRectRectCombinations();
foreach (RectRectCombination c, combinations) {
QTestData &testData = QTest::newRow(c.tag.toLatin1().data());
QRectF r1(c.x1, c.y1, c.w1, c.h1);
QRectF r2(c.x2, c.y2, c.w2, c.h2);
testData << r1 << r2;
if (includeProperArg)
testData << (i == 0);
}
}
}
struct RectPointCombination
{
QString tag;
qreal x, y, w, h, px, py;
RectPointCombination(
const QString &tag,
const qreal x, const qreal y, const qreal w, const qreal h, const qreal px, const qreal py)
: tag(tag), x(x), y(y), w(w), h(h), px(px), py(py) {}
};
static QList<RectPointCombination> createRectPointCombinations()
{
QList<RectPointCombination> result;
result << RectPointCombination("null", 0, 0, 0, 0, 0, 0);
result << RectPointCombination("miss", 0, 0, 10, 10, -1, -1);
result << RectPointCombination("contain", 0, 0, 10, 10, 0, 0);
result << RectPointCombination("contain_proper", 0, 0, 10, 10, 1, 1);
result << RectPointCombination("miss_flip", 9, 9, -10, -10, -1, -1);
result << RectPointCombination("contain_flip", 9, 9, -10, -10, 0, 0);
result << RectPointCombination("contain_flip_proper", 9, 9, -10, -10, 1, 1);
return result;
}
static void addRectPointData(bool includeProperArg = false)
{
QTest::addColumn<QRectF>("rf");
QTest::addColumn<QPointF>("pf");
if (includeProperArg)
QTest::addColumn<bool>("proper");
for (int i = 0; i < (includeProperArg ? 2 : 1); ++i) {
QList<RectPointCombination> combinations = createRectPointCombinations();
foreach (RectPointCombination c, combinations) {
QTestData &testData = QTest::newRow(c.tag.toLatin1().data());
QRectF r(c.x, c.y, c.w, c.h);
QPointF p(c.px, c.py);
testData << r << p;
if (includeProperArg)
testData << (i == 0);
}
}
}
void tst_QRect::contains_point_data()
{
addRectPointData(true);
}
void tst_QRect::contains_point()
{
QFETCH(QRectF, rf);
QFETCH(QPointF, pf);
QFETCH(bool, proper);
QRect r(rf.toRect());
QPoint p(pf.toPoint());
QBENCHMARK {
r.contains(p, proper);
}
}
void tst_QRect::contains_rect_data()
{
addRectRectData(true);
}
void tst_QRect::contains_rect()
{
QFETCH(QRectF, rf1);
QFETCH(QRectF, rf2);
QFETCH(bool, proper);
QRect r1(rf1.toRect());
QRect r2(rf2.toRect());
QBENCHMARK {
r1.contains(r2, proper);
}
}
void tst_QRect::intersects_data()
{
addRectRectData();
}
void tst_QRect::intersects()
{
QFETCH(QRectF, rf1);
QFETCH(QRectF, rf2);
QRect r1(rf1.toRect());
QRect r2(rf2.toRect());
QBENCHMARK {
r1.intersects(r2);
}
}
void tst_QRect::intersected_data()
{
addRectRectData();
}
void tst_QRect::intersected()
{
QFETCH(QRectF, rf1);
QFETCH(QRectF, rf2);
QRect r1(rf1.toRect());
QRect r2(rf2.toRect());
QBENCHMARK {
Q_UNUSED(r1.intersected(r2))
}
}
void tst_QRect::united_data()
{
addRectRectData();
}
void tst_QRect::united()
{
QFETCH(QRectF, rf1);
QFETCH(QRectF, rf2);
QRect r1(rf1.toRect());
QRect r2(rf2.toRect());
QBENCHMARK {
Q_UNUSED(r1.united(r2))
}
}
void tst_QRect::contains_point_f_data()
{
addRectPointData();
}
void tst_QRect::contains_point_f()
{
QFETCH(QRectF, rf);
QFETCH(QPointF, pf);
QBENCHMARK {
rf.contains(pf);
}
}
void tst_QRect::contains_rect_f_data()
{
addRectRectData();
}
void tst_QRect::contains_rect_f()
{
QFETCH(QRectF, rf1);
QFETCH(QRectF, rf2);
QBENCHMARK {
rf1.contains(rf2);
}
}
void tst_QRect::intersects_f_data()
{
addRectRectData();
}
void tst_QRect::intersects_f()
{
QFETCH(QRectF, rf1);
QFETCH(QRectF, rf2);
QBENCHMARK {
rf1.intersects(rf2);
}
}
void tst_QRect::intersected_f_data()
{
addRectRectData();
}
void tst_QRect::intersected_f()
{
QFETCH(QRectF, rf1);
QFETCH(QRectF, rf2);
QBENCHMARK {
Q_UNUSED(rf1.intersected(rf2))
}
}
void tst_QRect::united_f_data()
{
addRectRectData();
}
void tst_QRect::united_f()
{
QFETCH(QRectF, rf1);
QFETCH(QRectF, rf2);
QBENCHMARK {
Q_UNUSED(rf1.united(rf2))
}
}
QTEST_MAIN(tst_QRect)
#include "tst_bench_qrect.moc"

View File

@ -0,0 +1,14 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
#####################################################################
## tst_bench_qringbuffer Binary:
#####################################################################
qt_internal_add_benchmark(tst_bench_qringbuffer
SOURCES
tst_bench_qringbuffer.cpp
LIBRARIES
Qt::CorePrivate
Qt::Test
)

View File

@ -0,0 +1,46 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include <private/qringbuffer_p.h>
#include <QByteArray>
#include <qtest.h>
class tst_QRingBuffer : public QObject
{
Q_OBJECT
private slots:
void reserveAndRead();
void free();
};
void tst_QRingBuffer::reserveAndRead()
{
QRingBuffer ringBuffer;
QBENCHMARK {
for (qint64 i = 1; i < 256; ++i)
ringBuffer.reserve(i);
for (qint64 i = 1; i < 256; ++i)
ringBuffer.read(0, i);
}
}
void tst_QRingBuffer::free()
{
QRingBuffer ringBuffer;
QBENCHMARK {
ringBuffer.reserve(4096);
ringBuffer.reserve(2048);
ringBuffer.append(QByteArray("01234", 5));
ringBuffer.free(1);
ringBuffer.free(4096);
ringBuffer.free(48);
ringBuffer.free(2000);
}
}
QTEST_MAIN(tst_QRingBuffer)
#include "tst_bench_qringbuffer.moc"

View File

@ -0,0 +1,13 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
#####################################################################
## tst_bench_qset Binary:
#####################################################################
qt_internal_add_benchmark(tst_bench_qset
SOURCES
tst_bench_qset.cpp
LIBRARIES
Qt::Test
)

View File

@ -0,0 +1,103 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include <QSet>
#include <QTest>
class tst_QSet : public QObject
{
Q_OBJECT
private slots:
void intersect_int_data();
void intersect_int();
void intersect_complexType_data();
void intersect_complexType();
};
void tst_QSet::intersect_int_data()
{
QTest::addColumn<int>("lhsSize");
QTest::addColumn<int>("rhsSize");
QTest::addColumn<int>("intersectSize");
QTest::newRow("1000000.intersect(1000) = empty") << 1000000 << 1000 << 0;
QTest::newRow("1000.intersect(1000000) = empty") << 1000 << 1000000 << 0;
QTest::newRow("1000000.intersect(1000) = 500") << 1000000 << 1000 << 500;
QTest::newRow("1000.intersect(1000000) = 500") << 1000 << 1000000 << 500;
QTest::newRow("1000000.intersect(1000) = 1000") << 1000000 << 1000 << 1000;
QTest::newRow("1000.intersect(1000000) = 1000") << 1000 << 1000000 << 1000;
}
void tst_QSet::intersect_int()
{
QFETCH(int, lhsSize);
QFETCH(int, rhsSize);
QFETCH(int, intersectSize);
// E.g. when lhsSize = 1000, rhsSize = 1000000 and intersectSize = 500:
// lhsSize = { 0, 1, ... 1000 }
// rhsSize = { 500, 501, ... 1000500 }
QSet<int> lhs;
for (int i = 0; i < lhsSize; ++i)
lhs.insert(i);
QSet<int> rhs;
const int start = lhsSize - intersectSize;
for (int i = start; i < start + rhsSize; ++i)
rhs.insert(i);
QBENCHMARK {
lhs.intersect(rhs);
}
QVERIFY(lhs.size() == intersectSize);
}
struct ComplexType
{
ComplexType(int a) : a(a) {}
int a;
int b;
int c;
};
inline uint qHash(const ComplexType &key, uint seed = 0)
{
return uint(key.a) ^ seed;
}
inline bool operator==(const ComplexType &lhs, const ComplexType &rhs)
{
return lhs.a == rhs.a;
}
void tst_QSet::intersect_complexType_data()
{
intersect_int_data();
}
void tst_QSet::intersect_complexType()
{
QFETCH(int, lhsSize);
QFETCH(int, rhsSize);
QFETCH(int, intersectSize);
QSet<ComplexType> lhs;
for (int i = 0; i < lhsSize; ++i)
lhs.insert(ComplexType(i));
QSet<ComplexType> rhs;
const int start = lhsSize - intersectSize;
for (int i = start; i < start + rhsSize; ++i)
rhs.insert(ComplexType(i));
QBENCHMARK {
lhs.intersect(rhs);
}
}
QTEST_MAIN(tst_QSet)
#include "tst_bench_qset.moc"

View File

@ -0,0 +1,12 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
qt_internal_add_benchmark(tst_bench_shared_ptr
SOURCES
tst_bench_shared_ptr.cpp
INCLUDE_DIRECTORIES
.
LIBRARIES
Qt::Core
Qt::Test
)

View File

@ -0,0 +1,111 @@
// Copyright (C) 2021 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include <QObject>
#include <QScopeGuard>
#include <QSharedPointer>
#include <QTest>
#include <atomic>
#include <memory>
#include <thread>
#include <vector>
#if __has_include(<boost/shared_ptr.hpp>)
# include <boost/shared_ptr.hpp>
# include <boost/make_shared.hpp>
# ifdef BOOST_NO_EXCEPTIONS
// https://stackoverflow.com/a/9530546/134841
// https://www.boost.org/doc/libs/1_79_0/libs/throw_exception/doc/html/throw_exception.html#throw_exception
BOOST_NORETURN void boost::throw_exception(const std::exception &) { std::terminate(); }
# if BOOST_VERSION >= 107300
// https://www.boost.org/doc/libs/1_79_0/libs/throw_exception/doc/html/throw_exception.html#changes_in_1_73_0
BOOST_NORETURN void boost::throw_exception(const std::exception &, const boost::source_location &)
{ std::terminate(); }
# endif // Boost v1.73
# endif // BOOST_NO_EXCEPTIONS
# define ONLY_IF_BOOST(x) x
#else
# define ONLY_IF_BOOST(x) QSKIP("This benchmark requires Boost.SharedPtr.")
#endif
class tst_QSharedPointer : public QObject
{
Q_OBJECT
private Q_SLOTS:
void refAndDeref_null_QSP_int() { refAndDeref<QSharedPointer<int>>(); }
void refAndDeref_null_SSP_int() { refAndDeref<std::shared_ptr<int>>(); }
void refAndDeref_null_BSP_int() { ONLY_IF_BOOST(refAndDeref<boost::shared_ptr<int>>()); }
void refAndDeref_null_QSP_QString() { refAndDeref<QSharedPointer<QString>>(); }
void refAndDeref_null_SSP_QString() { refAndDeref<std::shared_ptr<QString>>(); }
void refAndDeref_null_BSP_QString() { ONLY_IF_BOOST(refAndDeref<boost::shared_ptr<QString>>()); }
void refAndDeref_nonnull_QSP_int() { refAndDeref(QSharedPointer<int>::create(42)); }
void refAndDeref_nonnull_SSP_int() { refAndDeref(std::make_shared<int>(42)); }
void refAndDeref_nonnull_BSP_int() { ONLY_IF_BOOST(refAndDeref(boost::make_shared<int>(42))); }
void refAndDeref_nonnull_QSP_QString() { refAndDeref(QSharedPointer<QString>::create(QStringLiteral("Hello"))); }
void refAndDeref_nonnull_SSP_QString() { refAndDeref(std::make_shared<QString>(QStringLiteral("Hello"))); }
void refAndDeref_nonnull_BSP_QString() { ONLY_IF_BOOST(refAndDeref(boost::make_shared<QString>(QStringLiteral("Hello")))); }
private:
template <typename SP>
void refAndDeref(SP sp = {})
{
QBENCHMARK {
[[maybe_unused]] auto copy = sp;
}
}
private Q_SLOTS:
void threadedRefAndDeref_null_QSP_int() { threadedRefAndDeref<QSharedPointer<int>>(); }
void threadedRefAndDeref_null_SSP_int() { threadedRefAndDeref<std::shared_ptr<int>>(); }
void threadedRefAndDeref_null_BSP_int() { ONLY_IF_BOOST(threadedRefAndDeref<boost::shared_ptr<int>>()); }
void threadedRefAndDeref_null_QSP_QString() { threadedRefAndDeref<QSharedPointer<QString>>(); }
void threadedRefAndDeref_null_SSP_QString() { threadedRefAndDeref<std::shared_ptr<QString>>(); }
void threadedRefAndDeref_null_BSP_QString() { ONLY_IF_BOOST(threadedRefAndDeref<boost::shared_ptr<QString>>()); }
void threadedRefAndDeref_nonnull_QSP_int() { threadedRefAndDeref(QSharedPointer<int>::create(42)); }
void threadedRefAndDeref_nonnull_SSP_int() { threadedRefAndDeref(std::make_shared<int>(42)); }
void threadedRefAndDeref_nonnull_BSP_int() { ONLY_IF_BOOST(threadedRefAndDeref(boost::make_shared<int>(42))); }
void threadedRefAndDeref_nonnull_QSP_QString() { threadedRefAndDeref(QSharedPointer<QString>::create(QStringLiteral("Hello"))); }
void threadedRefAndDeref_nonnull_SSP_QString() { threadedRefAndDeref(std::make_shared<QString>(QStringLiteral("Hello"))); }
void threadedRefAndDeref_nonnull_BSP_QString() { ONLY_IF_BOOST(threadedRefAndDeref(boost::make_shared<QString>(QStringLiteral("Hello")))); }
private:
template <typename SP>
void threadedRefAndDeref(SP sp = {})
{
std::atomic<bool> cancel = false;
std::vector<std::thread> threads;
const auto numCores = std::max(2U, std::thread::hardware_concurrency());
for (uint i = 0; i < numCores - 1; ++i) {
threads.emplace_back([sp, &cancel] {
while (!cancel.load(std::memory_order_relaxed)) {
for (int i = 0; i < 100; ++i)
[[maybe_unused]] auto copy = sp;
}
});
}
const auto join = qScopeGuard([&] {
cancel.store(true, std::memory_order_relaxed);
for (auto &t : threads)
t.join();
});
QBENCHMARK {
[[maybe_unused]] auto copy = sp;
}
}
};
QTEST_MAIN(tst_QSharedPointer)
#include "tst_bench_shared_ptr.moc"

View File

@ -0,0 +1,14 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
#####################################################################
## tst_bench_qstack Binary:
#####################################################################
qt_internal_add_benchmark(tst_bench_qstack
SOURCES
tst_bench_qstack.cpp
LIBRARIES
Qt::CorePrivate
Qt::Test
)

View File

@ -0,0 +1,59 @@
// Copyright (C) 2015 Robin Burchell <robin.burchell@viroteck.net>
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include <QStack>
#include <QDebug>
#include <QTest>
#include <vector>
class tst_QStack: public QObject
{
Q_OBJECT
private slots:
void qstack_push();
void qstack_pop();
void qstack_pushpopone();
};
const int N = 1000000;
void tst_QStack::qstack_push()
{
QStack<int> v;
QBENCHMARK {
for (int i = 0; i != N; ++i)
v.push(i);
v = QStack<int>();
}
}
void tst_QStack::qstack_pop()
{
QStack<int> v;
for (int i = 0; i != N; ++i)
v.push(i);
QBENCHMARK {
QStack<int> v2 = v;
for (int i = 0; i != N; ++i) {
v2.pop();
}
}
}
void tst_QStack::qstack_pushpopone()
{
QBENCHMARK {
QStack<int> v;
for (int i = 0; i != N; ++i) {
v.push(0);
v.pop();
}
}
}
QTEST_MAIN(tst_QStack)
#include "tst_bench_qstack.moc"

View File

@ -0,0 +1,17 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
#####################################################################
## tst_bench_qvector Binary:
#####################################################################
qt_internal_add_benchmark(tst_bench_qvector
SOURCES
tst_bench_qvector.cpp
outofline.cpp
INCLUDE_DIRECTORIES
.
LIBRARIES
Qt::CorePrivate
Qt::Test
)

View File

@ -0,0 +1,80 @@
// Copyright (C) 2021 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include <QList>
#include "qrawvector.h"
#include <vector>
// Used as accumulator in tests:
double accumulate = 0;
QVector<double> qvector_fill_and_return_helper()
{
QVector<double> v(million);
for (int i = 0; i != million; ++i)
v[i] = i;
return v;
}
QVector<double> qrawvector_fill_and_return_helper()
{
QRawVector<double> v(million);
for (int i = 0; i != million; ++i)
v[i] = i;
return v.mutateToVector();
}
QVector<double> mixedvector_fill_and_return_helper()
{
std::vector<double> v(million);
for (int i = 0; i != million; ++i)
v[i] = i;
return QVector<double>(v.begin(), v.end());
}
std::vector<double> stdvector_fill_and_return_helper()
{
std::vector<double> v(million);
for (int i = 0; i != million; ++i)
v[i] = i;
return v;
}
const QVectorData QVectorData::shared_null = { Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, false, 0 };
static inline int alignmentThreshold()
{
// malloc on 32-bit platforms should return pointers that are 8-byte aligned or more
// while on 64-bit platforms they should be 16-byte aligned or more
return 2 * sizeof(void*);
}
QVectorData *QVectorData::allocate(int size, int alignment)
{
return static_cast<QVectorData *>(alignment > alignmentThreshold() ? qMallocAligned(size, alignment) : ::malloc(size));
}
QT_BEGIN_NAMESPACE
QVectorData *QVectorData::reallocate(QVectorData *x, int newsize, int oldsize, int alignment)
{
if (alignment > alignmentThreshold())
return static_cast<QVectorData *>(qReallocAligned(x, newsize, oldsize, alignment));
return static_cast<QVectorData *>(realloc(x, newsize));
}
void QVectorData::free(QVectorData *x, int alignment)
{
if (alignment > alignmentThreshold())
qFreeAligned(x);
else
::free(x);
}
int QVectorData::grow(int sizeOfHeader, int size, int sizeOfT)
{
return qCalculateGrowingBlockSize(size, sizeOfT, sizeOfHeader).elementCount;
}
QT_END_NAMESPACE

View File

@ -0,0 +1,650 @@
// Copyright (C) 2021 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef QRAWVECTOR_H
#define QRAWVECTOR_H
#include <QtCore/qiterator.h>
#include <QtCore/qdebug.h>
#include <QtCore/qatomic.h>
#include <QtCore/qlist.h>
#include <QtCore/private/qtools_p.h>
#include <iterator>
#include <vector>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
const int million = 1000000;
extern double accumulate;
// Defined in outofline.cpp
extern QVector<double> qvector_fill_and_return_helper();
extern QVector<double> qrawvector_fill_and_return_helper();
extern std::vector<double> stdvector_fill_and_return_helper();
extern QVector<double> mixedvector_fill_and_return_helper();
QT_BEGIN_NAMESPACE
struct QVectorData
{
QtPrivate::RefCount ref;
int size;
uint alloc : 31;
uint capacityReserved : 1;
qptrdiff offset;
void* data() { return reinterpret_cast<char *>(this) + this->offset; }
static const QVectorData shared_null;
static QVectorData *allocate(int size, int alignment);
static QVectorData *reallocate(QVectorData *old, int newsize, int oldsize, int alignment);
static void free(QVectorData *data, int alignment);
static int grow(int sizeOfHeader, int size, int sizeOfT);
};
template <typename T>
struct QVectorTypedData : QVectorData
{
T* begin() { return reinterpret_cast<T *>(this->data()); }
T* end() { return begin() + this->size; }
static QVectorTypedData *sharedNull() { return static_cast<QVectorTypedData *>(const_cast<QVectorData *>(&QVectorData::shared_null)); }
};
template <typename T>
class QRawVector
{
typedef QVectorTypedData<T> Data;
T *m_begin;
int m_size;
int m_alloc;
public:
static Data *toBase(T *begin)
{ return (Data*)((char*)begin - offsetOfTypedData()); }
static T *fromBase(void *d)
{ return (T*)((char*)d + offsetOfTypedData()); }
inline QRawVector()
{ m_begin = fromBase(0); m_alloc = m_size = 0; realloc(m_size, m_alloc, true); }
explicit QRawVector(int size);
QRawVector(int size, const T &t);
inline QRawVector(const QRawVector<T> &v)
{ m_begin = v.m_begin; m_alloc = v.m_alloc; m_size = v.m_size; realloc(m_size, m_alloc, true); }
inline ~QRawVector() { free(m_begin, m_size); }
QRawVector<T> &operator=(const QRawVector<T> &v);
bool operator==(const QRawVector<T> &v) const;
inline bool operator!=(const QRawVector<T> &v) const { return !(*this == v); }
inline int size() const { return m_size; }
inline bool isEmpty() const { return m_size == 0; }
void resize(int size);
inline int capacity() const { return m_alloc; }
void reserve(int size);
inline void squeeze() { realloc(m_size, m_size, false); }
inline T *data() { return m_begin; }
inline const T *data() const { return m_begin; }
inline const T *constData() const { return m_begin; }
void clear();
const T &at(int i) const;
T &operator[](int i);
const T &operator[](int i) const;
void append(const T &t);
void prepend(const T &t);
void insert(int i, const T &t);
void insert(int i, int n, const T &t);
void replace(int i, const T &t);
void remove(int i);
void remove(int i, int n);
QRawVector<T> &fill(const T &t, int size = -1);
int indexOf(const T &t, int from = 0) const;
int lastIndexOf(const T &t, int from = -1) const;
bool contains(const T &t) const;
int count(const T &t) const;
// STL-style
typedef T *iterator;
typedef const T *const_iterator;
inline iterator begin() { return m_begin; }
inline const_iterator begin() const { return m_begin; }
inline const_iterator constBegin() const { return m_begin; }
inline iterator end() { return m_begin + m_size; }
inline const_iterator end() const { return m_begin + m_size; }
inline const_iterator constEnd() const { return m_begin + m_size; }
iterator insert(iterator before, int n, const T &x);
inline iterator insert(iterator before, const T &x) { return insert(before, 1, x); }
iterator erase(iterator begin, iterator end);
inline iterator erase(iterator pos) { return erase(pos, pos+1); }
// more Qt
inline int count() const { return m_size; }
inline T& first() { Q_ASSERT(!isEmpty()); return *begin(); }
inline const T &first() const { Q_ASSERT(!isEmpty()); return *begin(); }
inline T& last() { Q_ASSERT(!isEmpty()); return *(end()-1); }
inline const T &last() const { Q_ASSERT(!isEmpty()); return *(end()-1); }
inline bool startsWith(const T &t) const { return !isEmpty() && first() == t; }
inline bool endsWith(const T &t) const { return !isEmpty() && last() == t; }
QRawVector<T> mid(int pos, int length = -1) const;
T value(int i) const;
T value(int i, const T &defaultValue) const;
// STL compatibility
typedef T value_type;
typedef value_type *pointer;
typedef const value_type *const_pointer;
typedef value_type &reference;
typedef const value_type &const_reference;
typedef ptrdiff_t difference_type;
typedef iterator Iterator;
typedef const_iterator ConstIterator;
typedef int size_type;
inline void push_back(const T &t) { append(t); }
inline void push_front(const T &t) { prepend(t); }
void pop_back() { Q_ASSERT(!isEmpty()); erase(end()-1); }
void pop_front() { Q_ASSERT(!isEmpty()); erase(begin()); }
inline bool empty() const { return m_size == 0; }
inline T &front() { return first(); }
inline const_reference front() const { return first(); }
inline reference back() { return last(); }
inline const_reference back() const { return last(); }
// comfort
QRawVector<T> &operator+=(const QRawVector<T> &l);
inline QRawVector<T> operator+(const QRawVector<T> &l) const
{ QRawVector n = *this; n += l; return n; }
inline QRawVector<T> &operator+=(const T &t)
{ append(t); return *this; }
inline QRawVector<T> &operator<< (const T &t)
{ append(t); return *this; }
inline QRawVector<T> &operator<<(const QRawVector<T> &l)
{ *this += l; return *this; }
QList<T> toList() const;
//static QRawVector<T> fromList(const QList<T> &list);
static inline QRawVector<T> fromStdVector(const std::vector<T> &vector)
{ QRawVector<T> tmp; std::copy(vector.begin(), vector.end(), std::back_inserter(tmp)); return tmp; }
inline std::vector<T> toStdVector() const
{ std::vector<T> tmp; std::copy(constBegin(), constEnd(), std::back_inserter(tmp)); return tmp; }
private:
T *allocate(int alloc);
void realloc(int size, int alloc, bool ref);
void free(T *begin, int size);
class AlignmentDummy { QVectorData header; T array[1]; };
static constexpr int offsetOfTypedData()
{
// (non-POD)-safe offsetof(AlignmentDummy, array)
return (sizeof(QVectorData) + (alignOfTypedData() - 1)) & ~(alignOfTypedData() - 1);
}
static constexpr int alignOfTypedData()
{
return alignof(AlignmentDummy);
}
public:
QVector<T> mutateToVector()
{
Q_ASSERT(!"Fix QTBUG-95061 before calling this; it is broken beyond repair");
Data *d = toBase(m_begin);
d->ref.initializeOwned();
d->alloc = m_alloc;
d->size = m_size;
d->capacityReserved = 0;
d->offset = offsetOfTypedData();
QVector<T> v;
*reinterpret_cast<QVectorData **>(&v) = d;
m_begin = fromBase(0);
m_size = m_alloc = 0;
return v;
}
};
template <typename T>
void QRawVector<T>::reserve(int asize)
{ if (asize > m_alloc) realloc(m_size, asize, false); }
template <typename T>
void QRawVector<T>::resize(int asize)
{ realloc(asize, (asize > m_alloc || (asize < m_size && asize < (m_alloc >> 1)))
? QVectorData::grow(offsetOfTypedData(), asize, sizeof(T))
: m_alloc, false); }
template <typename T>
inline void QRawVector<T>::clear()
{ *this = QRawVector<T>(); }
template <typename T>
inline const T &QRawVector<T>::at(int i) const
{ Q_ASSERT_X(i >= 0 && i < m_size, "QRawVector<T>::at", "index out of range");
return m_begin[i]; }
template <typename T>
inline const T &QRawVector<T>::operator[](int i) const
{ Q_ASSERT_X(i >= 0 && i < m_size, "QRawVector<T>::operator[]", "index out of range");
return m_begin[i]; }
template <typename T>
inline T &QRawVector<T>::operator[](int i)
{ Q_ASSERT_X(i >= 0 && i < m_size, "QRawVector<T>::operator[]", "index out of range");
return data()[i]; }
template <typename T>
inline void QRawVector<T>::insert(int i, const T &t)
{ Q_ASSERT_X(i >= 0 && i <= m_size, "QRawVector<T>::insert", "index out of range");
insert(begin() + i, 1, t); }
template <typename T>
inline void QRawVector<T>::insert(int i, int n, const T &t)
{ Q_ASSERT_X(i >= 0 && i <= m_size, "QRawVector<T>::insert", "index out of range");
insert(begin() + i, n, t); }
template <typename T>
inline void QRawVector<T>::remove(int i, int n)
{ Q_ASSERT_X(i >= 0 && n >= 0 && i + n <= m_size, "QRawVector<T>::remove", "index out of range");
erase(begin() + i, begin() + i + n); }
template <typename T>
inline void QRawVector<T>::remove(int i)
{ Q_ASSERT_X(i >= 0 && i < m_size, "QRawVector<T>::remove", "index out of range");
erase(begin() + i, begin() + i + 1); }
template <typename T>
inline void QRawVector<T>::prepend(const T &t)
{ insert(begin(), 1, t); }
template <typename T>
inline void QRawVector<T>::replace(int i, const T &t)
{
Q_ASSERT_X(i >= 0 && i < m_size, "QRawVector<T>::replace", "index out of range");
const T copy(t);
data()[i] = copy;
}
template <typename T>
QRawVector<T> &QRawVector<T>::operator=(const QRawVector<T> &v)
{
if (this != &v) {
free(m_begin, m_size);
m_alloc = v.m_alloc;
m_size = v.m_size;
m_begin = v.m_begin;
realloc(m_size, m_alloc, true);
}
return *this;
}
template <typename T>
inline T *QRawVector<T>::allocate(int aalloc)
{
QVectorData *d = QVectorData::allocate(offsetOfTypedData() + aalloc * sizeof(T), alignOfTypedData());
Q_CHECK_PTR(d);
return fromBase(d);
}
template <typename T>
QRawVector<T>::QRawVector(int asize)
{
m_size = m_alloc = asize;
m_begin = allocate(asize);
if (QTypeInfo<T>::isComplex) {
T *b = m_begin;
T *i = m_begin + m_size;
while (i != b)
new (--i) T;
} else {
memset(m_begin, 0, asize * sizeof(T));
}
}
template <typename T>
QRawVector<T>::QRawVector(int asize, const T &t)
{
m_size = m_alloc = asize;
m_begin = allocate(asize);
T *i = m_begin + m_size;
while (i != m_begin)
new (--i) T(t);
}
template <typename T>
void QRawVector<T>::free(T *begin, int size)
{
if (QTypeInfo<T>::isComplex) {
T *i = begin + size;
while (i-- != begin)
i->~T();
}
Data *x = toBase(begin);
x->free(x, alignOfTypedData());
}
template <typename T>
void QRawVector<T>::realloc(int asize, int aalloc, bool ref)
{
if (QTypeInfo<T>::isComplex && asize < m_size && !ref) {
// call the destructor on all objects that need to be
// destroyed when shrinking
T *pOld = m_begin + m_size;
while (asize < m_size) {
(--pOld)->~T();
--m_size;
}
}
int xalloc = m_alloc;
int xsize = m_size;
bool changed = false;
T *xbegin = m_begin;
if (aalloc != xalloc || ref) {
// (re)allocate memory
if (!QTypeInfo<T>::isRelocatable) {
xbegin = allocate(aalloc);
xsize = 0;
changed = true;
} else if (ref) {
xbegin = allocate(aalloc);
if (QTypeInfo<T>::isComplex) {
xsize = 0;
} else {
::memcpy(xbegin, m_begin, qMin(aalloc, xalloc) * sizeof(T));
xsize = m_size;
}
changed = true;
} else {
QT_TRY {
QVectorData *mem = QVectorData::reallocate(toBase(m_begin),
offsetOfTypedData() + aalloc * sizeof(T),
offsetOfTypedData() + xalloc * sizeof(T), alignOfTypedData());
Q_CHECK_PTR(mem);
xbegin = fromBase(mem);
xsize = m_size;
} QT_CATCH (const std::bad_alloc &) {
if (aalloc > xalloc) // ignore the error in case we are just shrinking.
QT_RETHROW;
}
}
xalloc = aalloc;
}
if (QTypeInfo<T>::isComplex) {
QT_TRY {
T *pOld = m_begin + xsize;
T *pNew = xbegin + xsize;
// copy objects from the old array into the new array
while (xsize < qMin(asize, m_size)) {
new (pNew++) T(*pOld++);
++xsize;
}
// construct all new objects when growing
while (xsize < asize) {
new (pNew++) T;
++xsize;
}
} QT_CATCH (...) {
free(xbegin, xsize);
QT_RETHROW;
}
} else if (asize > xsize) {
// initialize newly allocated memory to 0
memset(xbegin + xsize, 0, (asize - xsize) * sizeof(T));
}
xsize = asize;
if (changed) {
if (!ref)
free(m_begin, m_size);
}
m_alloc = xalloc;
m_size = xsize;
m_begin = xbegin;
}
template<typename T>
Q_OUTOFLINE_TEMPLATE T QRawVector<T>::value(int i) const
{
return (i < 0 || i >= m_size) ? T() : m_begin[i];
}
template<typename T>
Q_OUTOFLINE_TEMPLATE T QRawVector<T>::value(int i, const T &defaultValue) const
{
return (i < 0 || i >= m_size) ? defaultValue : m_begin[i];
}
template <typename T>
void QRawVector<T>::append(const T &t)
{
if (m_size + 1 > m_alloc) {
const T copy(t);
realloc(m_size, QVectorData::grow(offsetOfTypedData(), m_size + 1, sizeof(T)), false);
if (QTypeInfo<T>::isComplex)
new (m_begin + m_size) T(copy);
else
m_begin[m_size] = copy;
} else {
if (QTypeInfo<T>::isComplex)
new (m_begin + m_size) T(t);
else
m_begin[m_size] = t;
}
++m_size;
}
template <typename T>
typename QRawVector<T>::iterator QRawVector<T>::insert(iterator before, size_type n, const T &t)
{
int offset = int(before - m_begin);
if (n != 0) {
const T copy(t);
if (m_size + n > m_alloc)
realloc(m_size, QVectorData::grow(offsetOfTypedData(), m_size + n, sizeof(T)), false);
if (!QTypeInfo<T>::isRelocatable) {
T *b = m_begin + m_size;
T *i = m_begin + m_size + n;
while (i != b)
new (--i) T;
i = m_begin + m_size;
T *j = i + n;
b = m_begin + offset;
while (i != b)
*--j = *--i;
i = b+n;
while (i != b)
*--i = copy;
} else {
T *b = m_begin + offset;
T *i = b + n;
memmove(i, b, (m_size - offset) * sizeof(T));
while (i != b)
new (--i) T(copy);
}
m_size += n;
}
return m_begin + offset;
}
template <typename T>
typename QRawVector<T>::iterator QRawVector<T>::erase(iterator abegin, iterator aend)
{
int f = int(abegin - m_begin);
int l = int(aend - m_begin);
int n = l - f;
if (QTypeInfo<T>::isComplex) {
std::copy(m_begin + l, m_begin + m_size, m_begin + f);
T *i = m_begin + m_size;
T *b = m_begin + m_size - n;
while (i != b) {
--i;
i->~T();
}
} else {
memmove(m_begin + f, m_begin + l, (m_size - l) * sizeof(T));
}
m_size -= n;
return m_begin + f;
}
template <typename T>
bool QRawVector<T>::operator==(const QRawVector<T> &v) const
{
if (m_size != v.m_size)
return false;
T* b = m_begin;
T* i = b + m_size;
T* j = v.m_begin + m_size;
while (i != b)
if (!(*--i == *--j))
return false;
return true;
}
template <typename T>
QRawVector<T> &QRawVector<T>::fill(const T &from, int asize)
{
const T copy(from);
resize(asize < 0 ? m_size : asize);
if (m_size) {
T *i = m_begin + m_size;
T *b = m_begin;
while (i != b)
*--i = copy;
}
return *this;
}
template <typename T>
QRawVector<T> &QRawVector<T>::operator+=(const QRawVector &l)
{
int newSize = m_size + l.m_size;
realloc(m_size, newSize, false);
T *w = m_begin + newSize;
T *i = l.m_begin + l.m_size;
T *b = l.m_begin;
while (i != b) {
if (QTypeInfo<T>::isComplex)
new (--w) T(*--i);
else
*--w = *--i;
}
m_size = newSize;
return *this;
}
template <typename T>
int QRawVector<T>::indexOf(const T &t, int from) const
{
if (from < 0)
from = qMax(from + m_size, 0);
if (from < m_size) {
T* n = m_begin + from - 1;
T* e = m_begin + m_size;
while (++n != e)
if (*n == t)
return n - m_begin;
}
return -1;
}
template <typename T>
int QRawVector<T>::lastIndexOf(const T &t, int from) const
{
if (from < 0)
from += m_size;
else if (from >= m_size)
from = m_size-1;
if (from >= 0) {
T* b = m_begin;
T* n = m_begin + from + 1;
while (n != b) {
if (*--n == t)
return n - b;
}
}
return -1;
}
template <typename T>
bool QRawVector<T>::contains(const T &t) const
{
T* b = m_begin;
T* i = m_begin + m_size;
while (i != b)
if (*--i == t)
return true;
return false;
}
template <typename T>
int QRawVector<T>::count(const T &t) const
{
int c = 0;
T* b = m_begin;
T* i = m_begin + m_size;
while (i != b)
if (*--i == t)
++c;
return c;
}
template <typename T>
Q_OUTOFLINE_TEMPLATE QRawVector<T> QRawVector<T>::mid(int pos, int length) const
{
if (length < 0)
length = size() - pos;
if (pos == 0 && length == size())
return *this;
QRawVector<T> copy;
if (pos + length > size())
length = size() - pos;
for (int i = pos; i < pos + length; ++i)
copy += at(i);
return copy;
}
template <typename T>
Q_OUTOFLINE_TEMPLATE QList<T> QRawVector<T>::toList() const
{
QList<T> result;
for (int i = 0; i < size(); ++i)
result.append(at(i));
return result;
}
/*template <typename T>
Q_OUTOFLINE_TEMPLATE QRawVector<T> QList<T>::toVector() const
{
QRawVector<T> result(size());
for (int i = 0; i < size(); ++i)
result[i] = at(i);
return result;
}
template <typename T>
QRawVector<T> QRawVector<T>::fromList(const QList<T> &list)
{
return list.toVector();
}
template <typename T>
QList<T> QList<T>::fromVector(const QRawVector<T> &vector)
{
return vector.toList();
}
*/
Q_DECLARE_SEQUENTIAL_ITERATOR(RawVector)
Q_DECLARE_MUTABLE_SEQUENTIAL_ITERATOR(RawVector)
QT_END_NAMESPACE
#endif // QRAWVECTOR_H

View File

@ -0,0 +1,228 @@
// Copyright (C) 2021 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include <QVector>
#include <QDebug>
#include <QTest>
#include "qrawvector.h"
#include <vector>
/* Using 'extern accumulate' causes some load making the loop resembling a
'simple inner loop' in 'real' applications.
*/
/* QRawVector::mutateToVector() hacks a semblance of a Qt 5 QVector.
However, Qt 6's QVector is Qt 6's QList and completely different in internal
layout. The QTypedArrayData inside it is also completely rearranged. Until
QRawVector can be rewritten to do whatever it's supposed to do in a
Qt6-compatible way, this test is suppressed, see QTBUG-95061.
*/
#define TEST_RAW 0
// TODO: is this still a thing ? (Dates from g++ 4.3.3 in 2009.)
// For some reason, both 'plain' and '-callgrind' create strange results
// (like varying instruction count for the same assembly code)
// So replace it by a plain loop and measure wall clock time.
//#undef QBENCHMARK
//#define QBENCHMARK for (int j = 0; j != 10000; ++j)
class tst_QVector: public QObject
{
Q_OBJECT
private slots:
void calibration();
// Pure Qt solution
void qvector_separator() { qWarning() << "QVector results: "; }
void qvector_const_read_access();
void qvector_mutable_read_access();
void qvector_pop_back();
void qvector_fill_and_return();
// Purre Standard solution
void stdvector() { qWarning() << "std::vector results: "; }
void stdvector_const_read_access();
void stdvector_mutable_read_access();
void stdvector_pop_back();
void stdvector_fill_and_return();
// Build using std, pass as QVector
void mixedvector() { qWarning() << "mixed results: "; }
void mixedvector_fill_and_return();
// Alternative implementation
void qrawvector_separator() { qWarning() << "QRawVector results: "; }
void qrawvector_const_read_access();
void qrawvector_mutable_read_access();
#if TEST_RAW
void qrawvector_fill_and_return();
#endif
};
void tst_QVector::calibration()
{
QVector<double> v(million);
for (int i = 0; i < million; ++i)
v[i] = i;
QBENCHMARK {
for (int i = 0; i < million; ++i)
accumulate += i;
}
}
///////////////////// QVector /////////////////////
void tst_QVector::qvector_const_read_access()
{
QVector<double> v(million);
for (int i = 0; i < million; ++i)
v[i] = i;
const QVector<double> &vc = v;
QBENCHMARK {
for (int i = 0; i < million; ++i)
accumulate += vc[i];
}
}
void tst_QVector::qvector_mutable_read_access()
{
QVector<double> v(million);
for (int i = 0; i < million; ++i)
v[i] = i;
QBENCHMARK {
for (int i = 0; i < million; ++i)
accumulate += v[i];
}
}
void tst_QVector::qvector_fill_and_return()
{
QBENCHMARK {
QVector<double> v = qvector_fill_and_return_helper();
accumulate += v[1];
}
}
///////////////////// QRawVector /////////////////////
void tst_QVector::qrawvector_const_read_access()
{
QRawVector<double> v(million);
for (int i = 0; i < million; ++i)
v[i] = i;
const QRawVector<double> &vc = v;
QBENCHMARK {
for (int i = vc.size(); --i >= 0;)
accumulate += vc[i];
}
}
void tst_QVector::qrawvector_mutable_read_access()
{
QRawVector<double> v(million);
for (int i = 0; i < million; ++i)
v[i] = i;
QBENCHMARK {
for (int i = 0; i < million; ++i)
accumulate += v[i];
}
}
void tst_QVector::qvector_pop_back()
{
const int c1 = 100000;
QVERIFY(million % c1 == 0);
QVector<int> v;
v.resize(million);
QBENCHMARK {
for (int i = 0; i < c1; ++i)
v.pop_back();
if (v.size() == 0)
v.resize(million);
}
}
#if TEST_RAW
void tst_QVector::qrawvector_fill_and_return()
{
QBENCHMARK {
QVector<double> v = qrawvector_fill_and_return_helper();
accumulate += v[1];
}
}
#endif
///////////////////// std::vector /////////////////////
void tst_QVector::stdvector_const_read_access()
{
std::vector<double> v(million);
for (int i = 0; i < million; ++i)
v[i] = i;
const std::vector<double> &vc = v;
QBENCHMARK {
for (int i = 0; i < million; ++i)
accumulate += vc[i];
}
}
void tst_QVector::stdvector_mutable_read_access()
{
std::vector<double> v(million);
for (int i = 0; i < million; ++i)
v[i] = i;
QBENCHMARK {
for (int i = 0; i < million; ++i)
accumulate += v[i];
}
}
void tst_QVector::stdvector_pop_back()
{
const int size = million / 10;
QVERIFY(million % size == 0);
std::vector<int> v;
v.resize(million);
QBENCHMARK {
for (int i = 0; i < size; ++i)
v.pop_back();
if (v.size() == 0)
v.resize(million);
}
}
void tst_QVector::stdvector_fill_and_return()
{
QBENCHMARK {
std::vector<double> v = stdvector_fill_and_return_helper();
accumulate += v[1];
}
}
///////////////////// mixed vector /////////////////////
void tst_QVector::mixedvector_fill_and_return()
{
QBENCHMARK {
std::vector<double> v = stdvector_fill_and_return_helper();
accumulate += v[1];
}
}
QTEST_MAIN(tst_QVector)
#include "tst_bench_qvector.moc"