From 02a5928fa5a9bd348af90ba8ed9f7ef675bcb8b7 Mon Sep 17 00:00:00 2001 From: Andrei Golubev Date: Thu, 29 Oct 2020 11:03:31 +0100 Subject: [PATCH] Add QList/QVector benchmark tests Added some simple benchmarks for QList insertion of 1 element Added same tests for QVector (within the same file) for 5.15 Task-number: QTBUG-87330 Task-number: QTBUG-86583 Pick-to: 5.15 Change-Id: I19a851c79cf5ce0329266883e99ecaf2d6b3df19 Reviewed-by: Thiago Macieira --- tests/benchmarks/corelib/tools/qlist/main.cpp | 266 +++++++++++++++++- 1 file changed, 265 insertions(+), 1 deletion(-) diff --git a/tests/benchmarks/corelib/tools/qlist/main.cpp b/tests/benchmarks/corelib/tools/qlist/main.cpp index e276509220..716a3061ae 100644 --- a/tests/benchmarks/corelib/tools/qlist/main.cpp +++ b/tests/benchmarks/corelib/tools/qlist/main.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -29,6 +29,8 @@ #include #include +#include + static const int N = 1000; struct MyBase @@ -135,6 +137,164 @@ private Q_SLOTS: void removeAll_movable(); void removeAll_complex_data(); void removeAll_complex(); + + // append 1 element: + void appendOne_int_data() const { commonBenchmark_data(); } + void appendOne_primitive_data() const { commonBenchmark_data(); } + void appendOne_movable_data() const { commonBenchmark_data(); } + void appendOne_complex_data() const { commonBenchmark_data(); } + void appendOne_QString_data() const { commonBenchmark_data(); } + + void appendOne_int() const { appendOne_impl(); } // QTBUG-87330 + void appendOne_primitive() const { appendOne_impl(); } + void appendOne_movable() const { appendOne_impl(); } + void appendOne_complex() const { appendOne_impl(); } + void appendOne_QString() const { appendOne_impl(); } + + // prepend 1 element: + void prependOne_int_data() const { commonBenchmark_data(); } + void prependOne_primitive_data() const { commonBenchmark_data(); } + void prependOne_movable_data() const { commonBenchmark_data(); } + void prependOne_complex_data() const { commonBenchmark_data(); } + void prependOne_QString_data() const { commonBenchmark_data(); } + + void prependOne_int() const { prependOne_impl(); } + void prependOne_primitive() const { prependOne_impl(); } + void prependOne_movable() const { prependOne_impl(); } + void prependOne_complex() const { prependOne_impl(); } + void prependOne_QString() const { prependOne_impl(); } + + // insert in middle 1 element: + void midInsertOne_int_data() const { commonBenchmark_data(); } + void midInsertOne_primitive_data() const { commonBenchmark_data(); } + void midInsertOne_movable_data() const { commonBenchmark_data(); } + void midInsertOne_complex_data() const { commonBenchmark_data(); } + void midInsertOne_QString_data() const { commonBenchmark_data(); } + + void midInsertOne_int() const { midInsertOne_impl(); } + void midInsertOne_primitive() const { midInsertOne_impl(); } + void midInsertOne_movable() const { midInsertOne_impl(); } + void midInsertOne_complex() const { midInsertOne_impl(); } + void midInsertOne_QString() const { midInsertOne_impl(); } + + // append/prepend 1 element - hard times for branch predictor: + void appendPrependOne_int_data() const { commonBenchmark_data(); } + void appendPrependOne_primitive_data() const { commonBenchmark_data(); } + void appendPrependOne_movable_data() const { commonBenchmark_data(); } + void appendPrependOne_complex_data() const { commonBenchmark_data(); } + void appendPrependOne_QString_data() const { commonBenchmark_data(); } + + void appendPrependOne_int() const { midInsertOne_impl(); } + void appendPrependOne_primitive() const { midInsertOne_impl(); } + void appendPrependOne_movable() const { midInsertOne_impl(); } + void appendPrependOne_complex() const { midInsertOne_impl(); } + void appendPrependOne_QString() const { midInsertOne_impl(); } + + // prepend half elements, then appen another half: + void prependAppendHalvesOne_int_data() const { commonBenchmark_data(); } + void prependAppendHalvesOne_primitive_data() const { commonBenchmark_data(); } + void prependAppendHalvesOne_movable_data() const { commonBenchmark_data(); } + void prependAppendHalvesOne_complex_data() const { commonBenchmark_data(); } + void prependAppendHalvesOne_QString_data() const { commonBenchmark_data(); } + + void prependAppendHalvesOne_int() const { midInsertOne_impl(); } + void prependAppendHalvesOne_primitive() const { midInsertOne_impl(); } + void prependAppendHalvesOne_movable() const { midInsertOne_impl(); } + void prependAppendHalvesOne_complex() const { midInsertOne_impl(); } + void prependAppendHalvesOne_QString() const { midInsertOne_impl(); } + +// For 5.15 we also want to compare against QVector +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + // append 1 element: + void qvector_appendOne_int_data() const { commonBenchmark_data(); } + void qvector_appendOne_primitive_data() const { commonBenchmark_data(); } + void qvector_appendOne_movable_data() const { commonBenchmark_data(); } + void qvector_appendOne_complex_data() const { commonBenchmark_data(); } + void qvector_appendOne_QString_data() const { commonBenchmark_data(); } + + void qvector_appendOne_int() const { appendOne_impl(); } // QTBUG-87330 + void qvector_appendOne_primitive() const { appendOne_impl(); } + void qvector_appendOne_movable() const { appendOne_impl(); } + void qvector_appendOne_complex() const { appendOne_impl(); } + void qvector_appendOne_QString() const { appendOne_impl(); } + + // prepend 1 element: + void qvector_prependOne_int_data() const { commonBenchmark_data(); } + void qvector_prependOne_primitive_data() const { commonBenchmark_data(); } + void qvector_prependOne_movable_data() const { commonBenchmark_data(); } + void qvector_prependOne_complex_data() const { commonBenchmark_data(); } + void qvector_prependOne_QString_data() const { commonBenchmark_data(); } + + void qvector_prependOne_int() const { prependOne_impl(); } + void qvector_prependOne_primitive() const { prependOne_impl(); } + void qvector_prependOne_movable() const { prependOne_impl(); } + void qvector_prependOne_complex() const { prependOne_impl(); } + void qvector_prependOne_QString() const { prependOne_impl(); } + + // insert in middle 1 element: + void qvector_midInsertOne_int_data() const { commonBenchmark_data(); } + void qvector_midInsertOne_primitive_data() const { commonBenchmark_data(); } + void qvector_midInsertOne_movable_data() const { commonBenchmark_data(); } + void qvector_midInsertOne_complex_data() const { commonBenchmark_data(); } + void qvector_midInsertOne_QString_data() const { commonBenchmark_data(); } + + void qvector_midInsertOne_int() const { midInsertOne_impl(); } + void qvector_midInsertOne_primitive() const { midInsertOne_impl(); } + void qvector_midInsertOne_movable() const { midInsertOne_impl(); } + void qvector_midInsertOne_complex() const { midInsertOne_impl(); } + void qvector_midInsertOne_QString() const { midInsertOne_impl(); } + + // append/prepend 1 element - hard times for branch predictor: + void qvector_appendPrependOne_int_data() const { commonBenchmark_data(); } + void qvector_appendPrependOne_primitive_data() const { commonBenchmark_data(); } + void qvector_appendPrependOne_movable_data() const { commonBenchmark_data(); } + void qvector_appendPrependOne_complex_data() const { commonBenchmark_data(); } + void qvector_appendPrependOne_QString_data() const { commonBenchmark_data(); } + + void qvector_appendPrependOne_int() const { midInsertOne_impl(); } + void qvector_appendPrependOne_primitive() const { midInsertOne_impl(); } + void qvector_appendPrependOne_movable() const { midInsertOne_impl(); } + void qvector_appendPrependOne_complex() const { midInsertOne_impl(); } + void qvector_appendPrependOne_QString() const { midInsertOne_impl(); } + + // prepend half elements, then appen another half: + void qvector_prependAppendHalvesOne_int_data() const { commonBenchmark_data(); } + void qvector_prependAppendHalvesOne_primitive_data() const + { + commonBenchmark_data(); + } + void qvector_prependAppendHalvesOne_movable_data() const { commonBenchmark_data(); } + void qvector_prependAppendHalvesOne_complex_data() const { commonBenchmark_data(); } + void qvector_prependAppendHalvesOne_QString_data() const { commonBenchmark_data(); } + + void qvector_prependAppendHalvesOne_int() const { midInsertOne_impl(); } + void qvector_prependAppendHalvesOne_primitive() const + { + midInsertOne_impl(); + } + void qvector_prependAppendHalvesOne_movable() const { midInsertOne_impl(); } + void qvector_prependAppendHalvesOne_complex() const { midInsertOne_impl(); } + void qvector_prependAppendHalvesOne_QString() const { midInsertOne_impl(); } +#endif + +private: + template + void commonBenchmark_data() const; + + template typename, typename> + void appendOne_impl() const; + + template typename, typename> + void prependOne_impl() const; + + template typename, typename> + void midInsertOne_impl() const; + + template typename, typename> + void appendPrependOne_impl() const; + + template typename, typename> + void prependAppendHalvesOne_impl() const; }; template @@ -231,6 +391,110 @@ void tst_QList::removeAll_complex() removeAll_test(i10, valueToRemove, itemsToRemove); } +template +void tst_QList::commonBenchmark_data() const +{ + QTest::addColumn("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") }) { + addRow(pair.first, pair.second); + } +} + +template typename Container, typename T> +void tst_QList::appendOne_impl() const +{ + QFETCH(int, elemCount); + constexpr auto getValue = []() { return T {}; }; + + QBENCHMARK { + Container container; + auto lvalue = getValue(); + + for (int i = 0; i < elemCount; ++i) { + container.append(lvalue); + } + } +} + +template typename Container, typename T> +void tst_QList::prependOne_impl() const +{ + QFETCH(int, elemCount); + constexpr auto getValue = []() { return T {}; }; + + QBENCHMARK { + Container container; + auto lvalue = getValue(); + + for (int i = 0; i < elemCount; ++i) { + container.prepend(lvalue); + } + } +} + +template typename Container, typename T> +void tst_QList::midInsertOne_impl() const +{ + QFETCH(int, elemCount); + constexpr auto getValue = []() { return T {}; }; + + QBENCHMARK { + Container container; + auto lvalue = getValue(); + + for (int i = 0; i < elemCount; ++i) { + container.insert(container.size() / 2, lvalue); + } + } +} + +template typename Container, typename T> +void tst_QList::appendPrependOne_impl() const +{ + QFETCH(int, elemCount); + constexpr auto getValue = []() { return T {}; }; + + QBENCHMARK { + Container container; + auto lvalue = getValue(); + + for (int i = 0; i < elemCount; ++i) { + if (i % 2 == 0) { + container.append(lvalue); + } else { + container.prepend(lvalue); + } + } + } +} + +template typename Container, typename T> +void tst_QList::prependAppendHalvesOne_impl() const +{ + QFETCH(int, elemCount); + constexpr auto getValue = []() { return T {}; }; + + QBENCHMARK { + Container 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); + } + } +} + QTEST_APPLESS_MAIN(tst_QList) #include "main.moc"