mirror of
https://github.com/crystalidea/qt6windows7.git
synced 2025-07-04 08:15:30 +08:00
qt 6.5.1 original
This commit is contained in:
16
tests/benchmarks/corelib/tools/CMakeLists.txt
Normal file
16
tests/benchmarks/corelib/tools/CMakeLists.txt
Normal 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)
|
@ -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
|
||||
)
|
@ -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"
|
@ -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
|
||||
)
|
@ -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"
|
@ -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
|
||||
)
|
@ -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"
|
@ -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
|
||||
)
|
@ -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"
|
16
tests/benchmarks/corelib/tools/qhash/CMakeLists.txt
Normal file
16
tests/benchmarks/corelib/tools/qhash/CMakeLists.txt
Normal 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
|
||||
)
|
56
tests/benchmarks/corelib/tools/qhash/outofline.cpp
Normal file
56
tests/benchmarks/corelib/tools/qhash/outofline.cpp
Normal 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
|
187
tests/benchmarks/corelib/tools/qhash/paths_small_data.txt
Normal file
187
tests/benchmarks/corelib/tools/qhash/paths_small_data.txt
Normal 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
|
149
tests/benchmarks/corelib/tools/qhash/tst_bench_qhash.cpp
Normal file
149
tests/benchmarks/corelib/tools/qhash/tst_bench_qhash.cpp
Normal 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"
|
36
tests/benchmarks/corelib/tools/qhash/tst_bench_qhash.h
Normal file
36
tests/benchmarks/corelib/tools/qhash/tst_bench_qhash.h
Normal 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
|
||||
|
13
tests/benchmarks/corelib/tools/qlist/CMakeLists.txt
Normal file
13
tests/benchmarks/corelib/tools/qlist/CMakeLists.txt
Normal 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
|
||||
)
|
410
tests/benchmarks/corelib/tools/qlist/tst_bench_qlist.cpp
Normal file
410
tests/benchmarks/corelib/tools/qlist/tst_bench_qlist.cpp
Normal 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"
|
15
tests/benchmarks/corelib/tools/qmap/CMakeLists.txt
Normal file
15
tests/benchmarks/corelib/tools/qmap/CMakeLists.txt
Normal 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
|
||||
)
|
304
tests/benchmarks/corelib/tools/qmap/tst_bench_qmap.cpp
Normal file
304
tests/benchmarks/corelib/tools/qmap/tst_bench_qmap.cpp
Normal 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"
|
13
tests/benchmarks/corelib/tools/qrect/CMakeLists.txt
Normal file
13
tests/benchmarks/corelib/tools/qrect/CMakeLists.txt
Normal 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
|
||||
)
|
291
tests/benchmarks/corelib/tools/qrect/tst_bench_qrect.cpp
Normal file
291
tests/benchmarks/corelib/tools/qrect/tst_bench_qrect.cpp
Normal 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"
|
14
tests/benchmarks/corelib/tools/qringbuffer/CMakeLists.txt
Normal file
14
tests/benchmarks/corelib/tools/qringbuffer/CMakeLists.txt
Normal 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
|
||||
)
|
@ -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"
|
13
tests/benchmarks/corelib/tools/qset/CMakeLists.txt
Normal file
13
tests/benchmarks/corelib/tools/qset/CMakeLists.txt
Normal 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
|
||||
)
|
103
tests/benchmarks/corelib/tools/qset/tst_bench_qset.cpp
Normal file
103
tests/benchmarks/corelib/tools/qset/tst_bench_qset.cpp
Normal 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"
|
12
tests/benchmarks/corelib/tools/qsharedpointer/CMakeLists.txt
Normal file
12
tests/benchmarks/corelib/tools/qsharedpointer/CMakeLists.txt
Normal 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
|
||||
)
|
@ -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"
|
14
tests/benchmarks/corelib/tools/qstack/CMakeLists.txt
Normal file
14
tests/benchmarks/corelib/tools/qstack/CMakeLists.txt
Normal 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
|
||||
)
|
59
tests/benchmarks/corelib/tools/qstack/tst_bench_qstack.cpp
Normal file
59
tests/benchmarks/corelib/tools/qstack/tst_bench_qstack.cpp
Normal 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"
|
17
tests/benchmarks/corelib/tools/qvector/CMakeLists.txt
Normal file
17
tests/benchmarks/corelib/tools/qvector/CMakeLists.txt
Normal 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
|
||||
)
|
80
tests/benchmarks/corelib/tools/qvector/outofline.cpp
Normal file
80
tests/benchmarks/corelib/tools/qvector/outofline.cpp
Normal 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
|
650
tests/benchmarks/corelib/tools/qvector/qrawvector.h
Normal file
650
tests/benchmarks/corelib/tools/qvector/qrawvector.h
Normal 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
|
228
tests/benchmarks/corelib/tools/qvector/tst_bench_qvector.cpp
Normal file
228
tests/benchmarks/corelib/tools/qvector/tst_bench_qvector.cpp
Normal 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"
|
Reference in New Issue
Block a user