/* Copyright (C) 2010 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.net, author Stephen Kelly This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #define KBIHASH 1 // #define BOOST_BIMAP 1 #define LEFT int #define RIGHT int // #define LEFT QString // #define RIGHT QString #ifdef KBIHASH #include "kbihash_p.h" #endif #ifdef BOOST_BIMAP #include #endif typedef QHash Hash; #ifdef KBIHASH typedef KBiHash Mapping; #endif #ifdef BOOST_BIMAP typedef boost::bimap Mapping; static Mapping hashToBiMap(const Hash &hash) { Mapping biMap; Hash::const_iterator it = hash.constBegin(); const Hash::const_iterator end = hash.constEnd(); for ( ; it != end; ++it) biMap.insert(Mapping::value_type(it.key(), it.value())); return biMap; } #endif // #define QBENCHMARK_ONCE #define MAX_SIZE 25000 #define MAX_DIGITS 5 #define NEW_ROW(num) \ QTest::newRow(QString("%1").arg(num).toLatin1() ) << num; template T containedValue(int value ); template<> int containedValue(int value) { return value; } template<> QString containedValue(int value) { return QString("%1").arg(value, MAX_DIGITS); } template T updatedValue(int value ); template<> int updatedValue(int value) { return value + MAX_SIZE; } template<> QString updatedValue(int value) { return QString("%1").arg(value + MAX_SIZE, MAX_DIGITS); } class BiHashBenchmarks : public QObject { Q_OBJECT public: BiHashBenchmarks(QObject* parent = 0) { qsrand(QDateTime::currentDateTime().toTime_t()); } private: Hash createHash(int numElements) { Hash hash; hash.reserve(numElements); for (int i = 0; i < numElements; ++i) { hash.insert(containedValue(i), containedValue(i)); } return hash; } void getTestData(); private slots: void testInsert(); void testLookup(); void testReverseLookup(); void testRemoveKey(); void testRemoveValue(); void testUpdateKey(); void testUpdateValue(); void testInsert_data(); void testLookup_data(); void testReverseLookup_data(); void testRemoveKey_data(); void testRemoveValue_data(); void testUpdateKey_data(); void testUpdateValue_data(); }; void BiHashBenchmarks::testInsert() { QFETCH(int, numElements); #ifdef KBIHASH Mapping biHash; QBENCHMARK_ONCE{ for (int i = 0; i < numElements; ++i) { biHash.insert(containedValue(i), containedValue(i)); } biHash.clear(); } #else # ifdef BOOST_BIMAP Mapping biMap; QBENCHMARK_ONCE{ for (int i = 0; i < numElements; ++i) { biMap.insert(Mapping::value_type(containedValue(i), containedValue(i))); } biMap.clear(); } # else Hash hash; QBENCHMARK_ONCE { for (int i = 0; i < numElements; ++i) { hash.insert(containedValue(i), containedValue(i)); } hash.clear(); } # endif #endif } void BiHashBenchmarks::getTestData() { QTest::addColumn("numElements"); NEW_ROW(1); NEW_ROW(2); NEW_ROW(3); NEW_ROW(5); NEW_ROW(8); NEW_ROW(13); NEW_ROW(21); NEW_ROW(34); NEW_ROW(50); NEW_ROW(100); NEW_ROW(150); NEW_ROW(200); NEW_ROW(250); NEW_ROW(500); NEW_ROW(1000); NEW_ROW(1500); NEW_ROW(2000); NEW_ROW(2500); NEW_ROW(5000); NEW_ROW(10000); NEW_ROW(15000); NEW_ROW(20000); NEW_ROW(MAX_SIZE); } void BiHashBenchmarks::testInsert_data() { getTestData(); } void BiHashBenchmarks::testLookup() { QFETCH(int, numElements); Hash hash = createHash(numElements); Hash::mapped_type result; const Hash::key_type key = containedValue(qrand() % numElements); #ifdef KBIHASH Mapping biHash = Mapping::fromHash(hash); QBENCHMARK_ONCE{ result = biHash.leftToRight(key); } #else # if BOOST_BIMAP Mapping biMap = hashToBiMap(hash); QBENCHMARK_ONCE{ result = biMap.left[key]; } # else QBENCHMARK_ONCE{ result = hash.value(key); } # endif #endif } void BiHashBenchmarks::testLookup_data() { getTestData(); } void BiHashBenchmarks::testReverseLookup() { QFETCH(int, numElements); Hash hash = createHash(numElements); Hash::key_type result; const Hash::mapped_type value = containedValue(qrand() % numElements); #ifdef KBIHASH Mapping biHash = Mapping::fromHash(hash); QBENCHMARK_ONCE{ result = biHash.rightToLeft(value); } #else # if BOOST_BIMAP Mapping biMap = hashToBiMap(hash); QBENCHMARK_ONCE{ result = biMap.right[value]; } # else QBENCHMARK_ONCE{ result = hash.key(value); } # endif #endif } void BiHashBenchmarks::testReverseLookup_data() { getTestData(); } void BiHashBenchmarks::testRemoveKey() { QFETCH(int, numElements); Hash hash = createHash(numElements); const Hash::key_type key = containedValue(qrand() % numElements); Hash::mapped_type value; #ifdef KBIHASH Mapping biHash = Mapping::fromHash(hash); QBENCHMARK_ONCE{ value = biHash.takeLeft(key); } #else # if BOOST_BIMAP Mapping biMap = hashToBiMap(hash); Mapping::size_type t; QBENCHMARK_ONCE{ t = biMap.erase(key); } # else QBENCHMARK_ONCE{ value = hash.take(key); } # endif #endif } void BiHashBenchmarks::testRemoveKey_data() { getTestData(); } void BiHashBenchmarks::testRemoveValue() { QFETCH(int, numElements); Hash hash = createHash(numElements); Hash::key_type result; const Hash::mapped_type value = containedValue(qrand() % numElements); #ifdef KBIHASH Mapping biHash = Mapping::fromHash(hash); QBENCHMARK_ONCE{ result = biHash.takeRight(value); } #else # ifdef BOOST_BIMAP Mapping biMap = hashToBiMap(hash); Mapping::size_type t; QBENCHMARK_ONCE{ t = biMap.right.erase(value); } # else QBENCHMARK_ONCE{ result = hash.key(value); hash.remove(result); } # endif #endif } void BiHashBenchmarks::testRemoveValue_data() { getTestData(); } void BiHashBenchmarks::testUpdateKey() { QFETCH(int, numElements); Hash hash = createHash(numElements); const int num = qrand() % numElements; const Hash::key_type oldKey = containedValue(num); const Hash::key_type newKey = updatedValue(num); #ifdef KBIHASH Mapping biHash = Mapping::fromHash(hash); QBENCHMARK_ONCE{ Mapping::right_iterator it = biHash.findRight(biHash.leftToRight(oldKey)); biHash.updateLeft(it, newKey); } #else # ifdef BOOST_BIMAP Mapping biMap = hashToBiMap(hash); QBENCHMARK_ONCE{ Mapping::right_iterator it = biMap.left.find(oldKey); it->first = newKey; } # else QBENCHMARK_ONCE{ const Hash::mapped_type value = hash.take(oldKey); hash.insert(newKey, value); } # endif #endif } void BiHashBenchmarks::testUpdateKey_data() { getTestData(); } void BiHashBenchmarks::testUpdateValue() { QFETCH(int, numElements); Hash hash = createHash(numElements); const int num = qrand() % numElements; const Hash::key_type key = containedValue(num); #ifdef KBIHASH Mapping biHash = Mapping::fromHash(hash); const Hash::mapped_type newValue = updatedValue(num); QBENCHMARK_ONCE{ Mapping::left_iterator it = biHash.findLeft(key); biHash.updateRight(it, newValue); } #else # if BOOST_BIMAP Mapping biMap = hashToBiMap(hash); const Hash::mapped_type newValue = updatedValue(num); QBENCHMARK_ONCE{ Mapping::left_iterator it = biMap.left.find(key); it->second = newValue; } # else const Hash::mapped_type newValue = updatedValue(num); QBENCHMARK_ONCE{ hash[key] = newValue; } # endif #endif } void BiHashBenchmarks::testUpdateValue_data() { getTestData(); } QTEST_MAIN(BiHashBenchmarks) #include "benchmarks.moc"