File indexing completed on 2024-05-19 04:39:26
0001 /* 0002 SPDX-FileCopyrightText: 2012-2013 Milian Wolff <mail@milianw.de> 0003 SPDX-FileCopyrightText: 2020 Igor Kushnir <igorkuo@gmail.com> 0004 0005 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0006 */ 0007 0008 #include "bench_indexedstring.h" 0009 0010 #include <language/util/kdevhash.h> 0011 #include <serialization/indexedstring.h> 0012 #include <tests/testhelpers.h> 0013 0014 #include <QTest> 0015 0016 #include <utility> 0017 #include <vector> 0018 0019 QTEST_GUILESS_MAIN(BenchIndexedString) 0020 0021 using namespace KDevelop; 0022 0023 static QVector<QString> generateData() 0024 { 0025 QVector<QString> data; 0026 static const int NUM_ITEMS = 100000; 0027 data.resize(NUM_ITEMS); 0028 for (int i = 0; i < NUM_ITEMS; ++i) { 0029 data[i] = QStringLiteral("/foo/%1").arg(i); 0030 } 0031 0032 return data; 0033 } 0034 0035 void BenchIndexedString::bench_index() 0036 { 0037 const QVector<QString> data = generateData(); 0038 QBENCHMARK { 0039 for (const QString& item : data) { 0040 IndexedString idx(item); 0041 Q_UNUSED(idx); 0042 } 0043 } 0044 } 0045 0046 static QVector<uint> setupTest() 0047 { 0048 const QVector<QString> data = generateData(); 0049 QVector<uint> indices; 0050 indices.reserve(data.size()); 0051 for (const QString& item : data) { 0052 IndexedString idx(item); 0053 indices << idx.index(); 0054 } 0055 0056 return indices; 0057 } 0058 0059 void BenchIndexedString::bench_length() 0060 { 0061 const QVector<uint> indices = setupTest(); 0062 QBENCHMARK { 0063 for (uint index : indices) { 0064 IndexedString str = IndexedString::fromIndex(index); 0065 str.length(); 0066 } 0067 } 0068 } 0069 0070 void BenchIndexedString::bench_qstring() 0071 { 0072 const QVector<uint> indices = setupTest(); 0073 QBENCHMARK { 0074 for (uint index : indices) { 0075 IndexedString str = IndexedString::fromIndex(index); 0076 str.str(); 0077 } 0078 } 0079 } 0080 0081 void BenchIndexedString::bench_kurl() 0082 { 0083 const QVector<uint> indices = setupTest(); 0084 QBENCHMARK { 0085 for (uint index : indices) { 0086 IndexedString str = IndexedString::fromIndex(index); 0087 str.toUrl(); 0088 } 0089 } 0090 } 0091 0092 void BenchIndexedString::bench_qhashQString() 0093 { 0094 const QVector<QString> data = generateData(); 0095 quint64 sum = 0; 0096 QBENCHMARK { 0097 for (const auto& string : data) { 0098 sum += qHash(string); 0099 } 0100 } 0101 QVERIFY(sum > 0); 0102 } 0103 0104 void BenchIndexedString::bench_qhashIndexedString() 0105 { 0106 const QVector<uint> indices = setupTest(); 0107 quint64 sum = 0; 0108 QBENCHMARK { 0109 for (uint index : indices) { 0110 sum += qHash(IndexedString::fromIndex(index)); 0111 } 0112 } 0113 QVERIFY(sum > 0); 0114 } 0115 0116 void BenchIndexedString::bench_hashString() 0117 { 0118 const QVector<QString> strings = generateData(); 0119 QVector<QByteArray> byteArrays; 0120 byteArrays.reserve(strings.size()); 0121 for (const auto& string : strings) { 0122 byteArrays << string.toUtf8(); 0123 } 0124 0125 quint64 sum = 0; 0126 QBENCHMARK { 0127 for (const auto& array : qAsConst(byteArrays)) { 0128 sum += IndexedString::hashString(array.constData(), array.length()); 0129 } 0130 } 0131 QVERIFY(sum > 0); 0132 } 0133 0134 void BenchIndexedString::bench_kdevhash() 0135 { 0136 const QVector<QString> strings = generateData(); 0137 QVector<QByteArray> byteArrays; 0138 byteArrays.reserve(strings.size()); 0139 for (const auto& string : strings) { 0140 byteArrays << string.toUtf8(); 0141 } 0142 0143 quint64 sum = 0; 0144 QBENCHMARK { 0145 for (const auto& array : qAsConst(byteArrays)) { 0146 sum += KDevHash() << array; 0147 } 0148 } 0149 QVERIFY(sum > 0); 0150 } 0151 0152 void BenchIndexedString::bench_qSet() 0153 { 0154 const QVector<uint> indices = setupTest(); 0155 QSet<IndexedString> set; 0156 QBENCHMARK { 0157 for (uint index : indices) { 0158 set.insert(IndexedString::fromIndex(index)); 0159 } 0160 } 0161 } 0162 0163 static std::vector<IndexedString> createIndexedStrings(std::size_t count) 0164 { 0165 std::vector<IndexedString> result; 0166 // result.reserve(count) is called after verifying that count is not too great. 0167 0168 constexpr char first{33}; 0169 constexpr char last{127}; 0170 constexpr std::size_t dataSize{4}; 0171 0172 std::size_t maxCount{1}; 0173 for (std::size_t i = 0; i < dataSize; ++i) { 0174 maxCount *= (last - first); 0175 } 0176 // Subtract 1 to account for the fact that count is checked at the beginning 0177 // of the innermost loop in order to support count == 0. 0178 --maxCount; 0179 QVERIFY_RETURN(count <= maxCount, result); 0180 0181 result.reserve(count); 0182 0183 char data[dataSize + 1] = {}; 0184 QCOMPARE_RETURN(data[dataSize], 0, result); 0185 for (char a = first; a != last; ++a) { 0186 data[0] = a; 0187 for (char b = first; b != last; ++b) { 0188 data[1] = b; 0189 for (char c = first; c != last; ++c) { 0190 data[2] = c; 0191 for (char d = first; d != last; ++d) { 0192 if (count-- == 0) { 0193 return result; 0194 } 0195 data[3] = d; 0196 result.emplace_back(data, dataSize); 0197 } 0198 } 0199 } 0200 } 0201 Q_UNREACHABLE(); 0202 } 0203 0204 void BenchIndexedString::bench_create() 0205 { 0206 QBENCHMARK_ONCE { 0207 createIndexedStrings(1'000'000); 0208 } 0209 } 0210 0211 void BenchIndexedString::bench_destroy() 0212 { 0213 auto strings = createIndexedStrings(10'000'000); 0214 QBENCHMARK_ONCE { 0215 strings = {}; 0216 } 0217 } 0218 0219 void BenchIndexedString::bench_swap() 0220 { 0221 IndexedString a("foo"); 0222 IndexedString b("bar"); 0223 QBENCHMARK { 0224 using std::swap; 0225 swap(a, b); 0226 } 0227 } 0228 0229 void BenchIndexedString::bench_string_vector_data() 0230 { 0231 QTest::addColumn<int>("type"); 0232 QTest::addRow("std::vector") << 0; 0233 QTest::addRow("QVector") << 1; 0234 } 0235 0236 void BenchIndexedString::bench_string_vector() 0237 { 0238 auto bench = [](auto container) { 0239 for (int i = 0; i < 10000; ++i) { 0240 container.push_back(IndexedString(QString::number(i))); 0241 } 0242 // deliberately do a worst-case remove-from-front here 0243 // we want to see how this performs without any noexcept move operators 0244 QBENCHMARK_ONCE { 0245 while (!container.empty()) { 0246 container.erase(container.begin()); 0247 } 0248 } 0249 }; 0250 0251 QFETCH(int, type); 0252 switch (type) { 0253 case 0: { 0254 std::vector<IndexedString> container; 0255 bench(container); 0256 break; 0257 } 0258 case 1: { 0259 QVector<IndexedString> container; 0260 bench(container); 0261 break; 0262 } 0263 default: 0264 QFAIL("unhandled type"); 0265 break; 0266 } 0267 } 0268 0269 #include "moc_bench_indexedstring.cpp"