You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
414 lines
8.7 KiB
414 lines
8.7 KiB
/* |
|
Copyright (C) 2010 Klarälvdalens Datakonsult AB, |
|
a KDAB Group company, info@kdab.net, |
|
author Stephen Kelly <stephen@kdab.com> |
|
|
|
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 <QtCore/QObject> |
|
#include <QtTest> |
|
|
|
#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 <boost/bimap.hpp> |
|
#endif |
|
|
|
typedef QHash<LEFT, RIGHT> Hash; |
|
|
|
#ifdef KBIHASH |
|
typedef KBiHash<LEFT, RIGHT> Mapping; |
|
#endif |
|
|
|
#ifdef BOOST_BIMAP |
|
typedef boost::bimap<LEFT, RIGHT> 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<typename T> T containedValue(int value ); |
|
|
|
template<> int containedValue(int value) |
|
{ |
|
return value; |
|
} |
|
|
|
template<> QString containedValue(int value) |
|
{ |
|
return QString("%1").arg(value, MAX_DIGITS); |
|
} |
|
|
|
template<typename T> 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<Hash::key_type>(i), containedValue<Hash::mapped_type>(i)); |
|
} |
|
return hash; |
|
} |
|
void getTestData(); |
|
|
|
private Q_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<Hash::key_type>(i), containedValue<Hash::mapped_type>(i)); |
|
} |
|
biHash.clear(); |
|
} |
|
#else |
|
# ifdef BOOST_BIMAP |
|
Mapping biMap; |
|
QBENCHMARK_ONCE{ |
|
for (int i = 0; i < numElements; ++i) |
|
{ |
|
biMap.insert(Mapping::value_type(containedValue<Hash::key_type>(i), containedValue<Hash::mapped_type>(i))); |
|
} |
|
biMap.clear(); |
|
} |
|
# else |
|
Hash hash; |
|
QBENCHMARK_ONCE { |
|
for (int i = 0; i < numElements; ++i) |
|
{ |
|
hash.insert(containedValue<Hash::key_type>(i), containedValue<Hash::mapped_type>(i)); |
|
} |
|
hash.clear(); |
|
} |
|
# endif |
|
#endif |
|
|
|
} |
|
|
|
void BiHashBenchmarks::getTestData() |
|
{ |
|
QTest::addColumn<int>("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<Hash::key_type>(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<Hash::mapped_type>(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<Hash::key_type>(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<Hash::mapped_type>(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<Hash::key_type>(num); |
|
const Hash::key_type newKey = updatedValue<Hash::key_type>(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<Hash::key_type>(num); |
|
|
|
#ifdef KBIHASH |
|
Mapping biHash = Mapping::fromHash(hash); |
|
const Hash::mapped_type newValue = updatedValue<Hash::mapped_type>(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<Hash::mapped_type>(num); |
|
QBENCHMARK_ONCE{ |
|
Mapping::left_iterator it = biMap.left.find(key); |
|
it->second = newValue; |
|
} |
|
# else |
|
const Hash::mapped_type newValue = updatedValue<Hash::mapped_type>(num); |
|
QBENCHMARK_ONCE{ |
|
hash[key] = newValue; |
|
} |
|
# endif |
|
#endif |
|
} |
|
|
|
void BiHashBenchmarks::testUpdateValue_data() |
|
{ |
|
getTestData(); |
|
} |
|
|
|
QTEST_MAIN(BiHashBenchmarks) |
|
#include "benchmarks.moc"
|
|
|