Commit e562aecb authored by Mark Olesen's avatar Mark Olesen
Browse files

HashTable performance: find(), found() check nElmts_ instead of tableSize_

- much better performance on empty tables (4-6x speedup), neutral
  performance change on filled tables. Since tableSize_ is non-zero when
  nElmts_ is, there is no modulus zero problem.
parent 9c8432a0
......@@ -32,6 +32,7 @@ Description
#include "boolList.H"
#include "PackedBoolList.H"
#include "HashSet.H"
#include "StaticHashTable.H"
#include "cpuTime.H"
#include <vector>
......@@ -55,11 +56,14 @@ int main(int argc, char *argv[])
labelHashSet emptyHash;
labelHashSet fullHash(1000);
for(label i = 0; i < n; i++)
for (label i = 0; i < n; i++)
{
fullHash.insert(i);
}
// don't use fullStaticHash, it's too slow
StaticHashTable<nil, label, Hash<label> > emptyStaticHash;
cpuTime timer;
for (label iter = 0; iter < nIters; ++iter)
......@@ -235,6 +239,22 @@ int main(int argc, char *argv[])
Info<< " sum " << sum << endl;
// Read empty static hash
sum = 0;
for (label iter = 0; iter < nIters; ++iter)
{
forAll(unpacked, i)
{
sum += emptyStaticHash.found(i);
}
}
Info<< "Reading empty StaticHash:" << timer.cpuTimeIncrement()
<< " s" << endl;
Info<< " sum " << sum << endl;
Info<< "Starting write tests" << endl;
//
// Write
//
......
......@@ -33,14 +33,14 @@ License
template<class Key, class Hash>
template<class AnyType>
Foam::HashSet<Key, Hash>::HashSet(const HashTable<AnyType, Key, Hash>& ht)
Foam::HashSet<Key, Hash>::HashSet(const HashTable<AnyType, Key, Hash>& h)
:
HashTable<nil, Key, Hash>(ht.size())
HashTable<nil, Key, Hash>(h.size())
{
for
(
typename HashTable<AnyType, Key, Hash>::const_iterator cit = ht.begin();
cit != ht.end();
typename HashTable<AnyType, Key, Hash>::const_iterator cit = h.cbegin();
cit != h.cend();
++cit
)
{
......@@ -62,7 +62,7 @@ template<class Key, class Hash>
bool Foam::HashSet<Key, Hash>::operator==(const HashSet<Key, Hash>& rhs) const
{
// Are all lhs elements in rhs?
for (const_iterator iter = this->begin(); iter != this->end(); ++iter)
for (const_iterator iter = this->cbegin(); iter != this->cend(); ++iter)
{
if (!rhs.found(iter.key()))
{
......@@ -71,7 +71,7 @@ bool Foam::HashSet<Key, Hash>::operator==(const HashSet<Key, Hash>& rhs) const
}
// Are all rhs elements in lhs?
for (const_iterator iter = rhs.begin(); iter != rhs.end(); ++iter)
for (const_iterator iter = rhs.cbegin(); iter != rhs.cend(); ++iter)
{
if (!found(iter.key()))
{
......@@ -94,7 +94,7 @@ template<class Key, class Hash>
void Foam::HashSet<Key, Hash>::operator|=(const HashSet<Key, Hash>& rhs)
{
// Add rhs elements into lhs
for (const_iterator iter = rhs.begin(); iter != rhs.end(); ++iter)
for (const_iterator iter = rhs.cbegin(); iter != rhs.cend(); ++iter)
{
insert(iter.key());
}
......@@ -105,7 +105,7 @@ template<class Key, class Hash>
void Foam::HashSet<Key, Hash>::operator&=(const HashSet<Key, Hash>& rhs)
{
// Remove elements not also found in rhs
for (iterator iter = this->begin(); iter != this->end(); ++iter)
for (iterator iter = this->cbegin(); iter != this->cend(); ++iter)
{
if (!rhs.found(iter.key()))
{
......@@ -119,7 +119,7 @@ template<class Key, class Hash>
void Foam::HashSet<Key, Hash>::operator^=(const HashSet<Key, Hash>& rhs)
{
// Add missed rhs elements, remove duplicate elements
for (const_iterator iter = rhs.begin(); iter != rhs.end(); ++iter)
for (const_iterator iter = rhs.cbegin(); iter != rhs.cend(); ++iter)
{
if (found(iter.key()))
{
......@@ -138,7 +138,7 @@ template<class Key, class Hash>
void Foam::HashSet<Key, Hash>::operator-=(const HashSet<Key, Hash>& rhs)
{
// Remove rhs elements from lhs
for (const_iterator iter = rhs.begin(); iter != rhs.end(); ++iter)
for (const_iterator iter = rhs.cbegin(); iter != rhs.cend(); ++iter)
{
erase(iter.key());
}
......
......@@ -71,7 +71,7 @@ Foam::HashTable<T, Key, Hash>::HashTable(const HashTable<T, Key, Hash>& ht)
table_[hashIdx] = 0;
}
for (const_iterator iter = ht.begin(); iter != ht.end(); ++iter)
for (const_iterator iter = ht.cbegin(); iter != ht.cend(); ++iter)
{
insert(iter.key(), *iter);
}
......@@ -113,9 +113,9 @@ Foam::HashTable<T, Key, Hash>::~HashTable()
template<class T, class Key, class Hash>
bool Foam::HashTable<T, Key, Hash>::found(const Key& key) const
{
if (tableSize_)
if (nElmts_)
{
label hashIdx = Hash()(key, tableSize_);
const label hashIdx = Hash()(key, tableSize_);
for (hashedEntry* ep = table_[hashIdx]; ep; ep = ep->next_)
{
......@@ -145,9 +145,9 @@ Foam::HashTable<T, Key, Hash>::find
const Key& key
)
{
if (tableSize_)
if (nElmts_)
{
label hashIdx = Hash()(key, tableSize_);
const label hashIdx = Hash()(key, tableSize_);
for (hashedEntry* ep = table_[hashIdx]; ep; ep = ep->next_)
{
......@@ -177,7 +177,7 @@ Foam::HashTable<T, Key, Hash>::find
const Key& key
) const
{
if (tableSize_)
if (nElmts_)
{
label hashIdx = Hash()(key, tableSize_);
......@@ -198,7 +198,7 @@ Foam::HashTable<T, Key, Hash>::find
}
# endif
return end();
return cend();
}
......@@ -209,7 +209,7 @@ Foam::List<Key> Foam::HashTable<T, Key, Hash>::toc() const
List<Key> tofc(nElmts_);
label i = 0;
for (const_iterator iter = begin(); iter != end(); ++iter)
for (const_iterator iter = cbegin(); iter != cend(); ++iter)
{
tofc[i++] = iter.key();
}
......@@ -351,7 +351,7 @@ bool Foam::HashTable<T, Key, Hash>::erase(const iterator& cit)
else
{
// No previous found. Mark with special value which is
// - not end()
// - not end()/cend()
// - handled by operator++
it.elmtPtr_ = reinterpret_cast<hashedEntry*>(this);
it.hashIndex_ = -1;
......@@ -466,7 +466,7 @@ void Foam::HashTable<T, Key, Hash>::resize(const label newSize)
HashTable<T, Key, Hash>* newTable = new HashTable<T, Key, Hash>(newSize);
for (const_iterator iter = begin(); iter != end(); ++iter)
for (const_iterator iter = cbegin(); iter != cend(); ++iter)
{
newTable->insert(iter.key(), *iter);
}
......@@ -565,7 +565,7 @@ void Foam::HashTable<T, Key, Hash>::operator=
clear();
}
for (const_iterator iter = rhs.begin(); iter != rhs.end(); ++iter)
for (const_iterator iter = rhs.cbegin(); iter != rhs.cend(); ++iter)
{
insert(iter.key(), *iter);
}
......@@ -579,22 +579,22 @@ bool Foam::HashTable<T, Key, Hash>::operator==
) const
{
// Are all my elements in rhs?
for (const_iterator iter = begin(); iter != end(); ++iter)
for (const_iterator iter = cbegin(); iter != cend(); ++iter)
{
const_iterator fnd = rhs.find(iter.key());
if (fnd == rhs.end() || fnd() != iter())
if (fnd == rhs.cend() || fnd() != iter())
{
return false;
}
}
// Are all rhs elements in me?
for (const_iterator iter = rhs.begin(); iter != rhs.end(); ++iter)
for (const_iterator iter = rhs.cbegin(); iter != rhs.cend(); ++iter)
{
const_iterator fnd = find(iter.key());
if (fnd == end() || fnd() != iter())
if (fnd == cend() || fnd() != iter())
{
return false;
}
......
......@@ -112,7 +112,7 @@ inline const T& Foam::HashTable<T, Key, Hash>::operator[](const Key& key) const
{
const_iterator iter = find(key);
if (iter == end())
if (iter == cend())
{
FatalErrorIn("HashTable<T, Key, Hash>::operator[](const Key&) const")
<< key << " not found in table. Valid entries: "
......@@ -283,8 +283,15 @@ Foam::HashTable<T, Key, Hash>::begin()
{
label i = 0;
while (table_ && !table_[i] && ++i < tableSize_)
{}
if (nElmts_)
{
while (table_ && !table_[i] && ++i < tableSize_)
{}
}
else
{
i = tableSize_;
}
if (i == tableSize_)
{
......@@ -456,8 +463,15 @@ Foam::HashTable<T, Key, Hash>::cbegin() const
{
label i = 0;
while (table_ && !table_[i] && ++i < tableSize_)
{}
if (nElmts_)
{
while (table_ && !table_[i] && ++i < tableSize_)
{}
}
else
{
i = tableSize_;
}
if (i == tableSize_)
{
......
......@@ -39,7 +39,7 @@ Foam::HashTable<T, Key, Hash>::HashTable(Istream& is, const label size)
endIter_(*this, NULL, 0),
endConstIter_(*this, NULL, 0)
{
for (label i=0; i<tableSize_; i++)
for (label i=0; i < tableSize_; i++)
{
table_[i] = 0;
}
......@@ -133,10 +133,13 @@ Foam::Istream& Foam::operator>>(Istream& is, HashTable<T, Key, Hash>& L)
)
{
is.putBack(lastToken);
Key key;
is >> key;
T element;
is >> element;
L.insert(key, element);
is.fatalCheck
......@@ -174,8 +177,8 @@ Foam::Ostream& Foam::operator<<(Ostream& os, const HashTable<T, Key, Hash>& L)
// Write contents
for
(
typename HashTable<T, Key, Hash>::const_iterator iter = L.begin();
iter != L.end();
typename HashTable<T, Key, Hash>::const_iterator iter = L.cbegin();
iter != L.cend();
++iter
)
{
......
......@@ -101,14 +101,17 @@ Foam::StaticHashTable<T, Key, Hash>::~StaticHashTable()
template<class T, class Key, class Hash>
bool Foam::StaticHashTable<T, Key, Hash>::found(const Key& key) const
{
label hashIdx = Hash()(key, keys_.size());
const List<Key>& localKeys = keys_[hashIdx];
forAll(localKeys, elemIdx)
if (nElmts_)
{
if (key == localKeys[elemIdx])
label hashIdx = Hash()(key, keys_.size());
const List<Key>& localKeys = keys_[hashIdx];
forAll(localKeys, elemIdx)
{
return true;
if (key == localKeys[elemIdx])
{
return true;
}
}
}
......@@ -131,14 +134,17 @@ Foam::StaticHashTable<T, Key, Hash>::find
const Key& key
)
{
label hashIdx = Hash()(key, keys_.size());
const List<Key>& localKeys = keys_[hashIdx];
forAll(localKeys, elemIdx)
if (nElmts_)
{
if (key == localKeys[elemIdx])
label hashIdx = Hash()(key, keys_.size());
const List<Key>& localKeys = keys_[hashIdx];
forAll(localKeys, elemIdx)
{
return iterator(*this, hashIdx, elemIdx);
if (key == localKeys[elemIdx])
{
return iterator(*this, hashIdx, elemIdx);
}
}
}
......
......@@ -102,7 +102,7 @@ inline const T& Foam::StaticHashTable<T, Key, Hash>::operator[]
{
const_iterator iter = find(key);
if (iter == end())
if (iter == cend())
{
FatalErrorIn
(
......
......@@ -33,7 +33,7 @@ License
template<class T, class Key, class Hash>
Foam::StaticHashTable<T, Key, Hash>::StaticHashTable
(
Istream& is,
Istream& is,
const label size
)
:
......@@ -142,10 +142,13 @@ Foam::Istream& Foam::operator>>(Istream& is, StaticHashTable<T, Key, Hash>& L)
)
{
is.putBack(lastToken);
Key key;
is >> key;
T element;
is >> element;
L.insert(key, element);
is.fatalCheck
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment