Warning, file /kdevelop/kdevelop/kdevplatform/language/duchain/tests/bench_hashes.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 SPDX-FileCopyrightText: 2012 Milian Wolff <mail@milianw.de> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "bench_hashes.h" 0008 0009 #include <serialization/indexedstring.h> 0010 0011 #include <tests/testcore.h> 0012 #include <tests/autotestshell.h> 0013 #include <QDateTime> 0014 #include <QVector> 0015 #include <QTest> 0016 0017 #include <unordered_map> 0018 0019 // similar to e.g. modificationrevision.cpp 0020 struct DataT 0021 { 0022 QDateTime a; 0023 QDateTime b; 0024 }; 0025 0026 using DataPair = QPair<KDevelop::IndexedString, DataT>; 0027 using InputData = QVector<DataPair>; 0028 0029 struct IndexedStringHash 0030 { 0031 inline uint operator()(const KDevelop::IndexedString& str) const 0032 { 0033 return str.hash(); 0034 } 0035 }; 0036 0037 using StlHash = std::unordered_map<KDevelop::IndexedString, DataT, IndexedStringHash>; 0038 0039 inline void insertData(StlHash& hash, const InputData& data) 0040 { 0041 for (const DataPair& pair : data) { 0042 hash.insert(std::make_pair(pair.first, pair.second)); 0043 } 0044 } 0045 0046 using QStringHash = QHash<KDevelop::IndexedString, DataT>; 0047 inline void insertData(QStringHash& hash, const InputData& data) 0048 { 0049 for (const DataPair& pair : data) { 0050 hash.insert(pair.first, pair.second); 0051 } 0052 } 0053 0054 QTEST_GUILESS_MAIN(BenchHashes) 0055 0056 using namespace KDevelop; 0057 0058 Q_DECLARE_METATYPE(InputData) 0059 0060 void BenchHashes::initTestCase() 0061 { 0062 AutoTestShell::init(); 0063 TestCore::initialize(Core::NoUi); 0064 0065 qRegisterMetaType<InputData>(); 0066 } 0067 0068 void BenchHashes::cleanupTestCase() 0069 { 0070 TestCore::shutdown(); 0071 } 0072 0073 void BenchHashes::feedData() 0074 { 0075 QTest::addColumn<bool>("useStl"); 0076 QTest::addColumn<InputData>("data"); 0077 0078 InputData data; 0079 const QVector<int> sizes{100, 1000, 10000, 100000}; 0080 for (int size : sizes) { 0081 for (int i = data.size(); i < size; ++i) { 0082 data << qMakePair(IndexedString(QString::number(i)), DataT()); 0083 } 0084 0085 QCOMPARE(data.size(), size); 0086 QTest::newRow(qPrintable(QStringLiteral("unordered_map-%1").arg(size))) 0087 << true << data; 0088 QTest::newRow(qPrintable(QStringLiteral("qhash-%1").arg(size))) 0089 << false << data; 0090 } 0091 } 0092 0093 void BenchHashes::insert() 0094 { 0095 QFETCH(bool, useStl); 0096 QFETCH(InputData, data); 0097 0098 if (useStl) { 0099 QBENCHMARK { 0100 StlHash hash; 0101 insertData(hash, data); 0102 } 0103 } else { 0104 QBENCHMARK { 0105 QStringHash hash; 0106 insertData(hash, data); 0107 } 0108 } 0109 } 0110 0111 void BenchHashes::insert_data() 0112 { 0113 feedData(); 0114 } 0115 0116 void BenchHashes::find() 0117 { 0118 QFETCH(bool, useStl); 0119 QFETCH(const InputData, data); 0120 0121 if (useStl) { 0122 StlHash hash; 0123 insertData(hash, data); 0124 QBENCHMARK { 0125 for (const DataPair& pair : data) { 0126 ( void ) hash.find(pair.first); 0127 } 0128 } 0129 } else { 0130 QStringHash hash; 0131 insertData(hash, data); 0132 QBENCHMARK { 0133 for (const DataPair& pair : data) { 0134 ( void ) hash.find(pair.first); 0135 } 0136 } 0137 } 0138 } 0139 0140 void BenchHashes::find_data() 0141 { 0142 feedData(); 0143 } 0144 0145 void BenchHashes::constFind() 0146 { 0147 QFETCH(bool, useStl); 0148 QFETCH(const InputData, data); 0149 0150 if (useStl) { 0151 StlHash hash; 0152 insertData(hash, data); 0153 const StlHash& constHash = hash; 0154 QBENCHMARK { 0155 for (const DataPair& pair : data) { 0156 ( void ) constHash.find(pair.first); 0157 } 0158 } 0159 } else { 0160 QStringHash hash; 0161 insertData(hash, data); 0162 QBENCHMARK { 0163 for (const DataPair& pair : data) { 0164 ( void ) hash.constFind(pair.first); 0165 } 0166 } 0167 } 0168 } 0169 0170 void BenchHashes::constFind_data() 0171 { 0172 feedData(); 0173 } 0174 0175 void BenchHashes::remove() 0176 { 0177 QFETCH(bool, useStl); 0178 QFETCH(const InputData, data); 0179 0180 if (useStl) { 0181 StlHash hash; 0182 insertData(hash, data); 0183 QBENCHMARK { 0184 for (const DataPair& pair : data) { 0185 hash.erase(pair.first); 0186 } 0187 } 0188 } else { 0189 QStringHash hash; 0190 insertData(hash, data); 0191 QBENCHMARK { 0192 for (const DataPair& pair : data) { 0193 hash.remove(pair.first); 0194 } 0195 } 0196 } 0197 } 0198 0199 void BenchHashes::remove_data() 0200 { 0201 feedData(); 0202 } 0203 0204 struct TypeRepoTestData 0205 { 0206 size_t size = 0; 0207 void* ptr = nullptr; 0208 }; 0209 0210 /** 0211 * somewhat artificial benchmark to test speed impact if we'd ever change 0212 * the underlying data type of the TypeSystem / TypeRegister. 0213 */ 0214 void BenchHashes::typeRepo() 0215 { 0216 QFETCH(int, type); 0217 if (type == 1 || type == 2) { 0218 QVector<TypeRepoTestData*> v; 0219 for (int i = 0; i < 100; ++i) { 0220 v.append(new TypeRepoTestData); 0221 } 0222 0223 if (type == 1) { 0224 QBENCHMARK { 0225 for (int i = 0; i < 100; ++i) { 0226 v.at(i)->size++; 0227 } 0228 } 0229 } else if (type == 2) { 0230 TypeRepoTestData** a = v.data(); 0231 QBENCHMARK { 0232 for (int i = 0; i < 100; ++i) { 0233 a[i]->size++; 0234 } 0235 } 0236 } 0237 qDeleteAll(v); 0238 } else if (type == 3) { 0239 QHash<int, TypeRepoTestData*> v; 0240 for (int i = 0; i < 100; ++i) { 0241 v[i] = new TypeRepoTestData; 0242 } 0243 0244 QBENCHMARK { 0245 for (int i = 0; i < 100; ++i) { 0246 v.value(i)->size++; 0247 } 0248 } 0249 qDeleteAll(v); 0250 } else if (type == 4) { 0251 QMap<int, TypeRepoTestData*> v; 0252 for (int i = 0; i < 100; ++i) { 0253 v[i] = new TypeRepoTestData; 0254 } 0255 0256 QBENCHMARK { 0257 for (int i = 0; i < 100; ++i) { 0258 v.value(i)->size++; 0259 } 0260 } 0261 qDeleteAll(v); 0262 } else if (type == 5) { 0263 std::unordered_map<int, TypeRepoTestData*> v; 0264 for (int i = 0; i < 100; ++i) { 0265 v[i] = new TypeRepoTestData; 0266 } 0267 0268 QBENCHMARK { 0269 for (int i = 0; i < 100; ++i) { 0270 v.at(i)->size++; 0271 } 0272 } 0273 for (const auto& [key, value] : v) { 0274 delete value; 0275 } 0276 } else if (type == 6) { 0277 // for the idea, look at c++'s lexer.cpp 0278 const int vectors = 5; 0279 using Pair = QPair<int, TypeRepoTestData*>; 0280 using InnerVector = QVarLengthArray<Pair, vectors>; 0281 QVarLengthArray <InnerVector, 10> v; 0282 v.resize(vectors); 0283 for (int i = 0; i < 100; ++i) { 0284 v[i % vectors] << qMakePair(i, new TypeRepoTestData); 0285 } 0286 0287 QBENCHMARK { 0288 for (int i = 0; i < 100; ++i) { 0289 for (const Pair& p : qAsConst(v.at(i % vectors))) { 0290 if (p.first == i) { 0291 p.second->size++; 0292 break; 0293 } 0294 } 0295 } 0296 } 0297 for (const auto& inner : v) { 0298 for (const auto& [key, value] : inner) { 0299 delete value; 0300 } 0301 } 0302 } else if (type == 0) { 0303 QBENCHMARK {} 0304 } 0305 } 0306 0307 void BenchHashes::typeRepo_data() 0308 { 0309 QTest::addColumn<int>("type"); 0310 0311 QTest::newRow("noop") << 0; 0312 QTest::newRow("vector") << 1; 0313 QTest::newRow("vector-raw") << 2; 0314 QTest::newRow("qhash") << 3; 0315 QTest::newRow("qmap") << 4; 0316 QTest::newRow("unordered_map") << 5; 0317 QTest::newRow("nested-vector") << 6; 0318 } 0319 0320 #include "moc_bench_hashes.cpp"