mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
HashTbl avoid backward search in erase()
- The ideas as discussed in email - The speedup is really there. Before loop 0 - Erased 100000 elements: 3.82 s loop 1 - Erased 100000 elements: 11.45 s loop 2 - Erased 100000 elements: 19.46 s loop 3 - Erased 100000 elements: 27.73 s loop 4 - Erased 100000 elements: 38.74 s ^C After loop 0 - Erased 100000 elements (size 2900000 capacity 8388608) 0.01 s loop 1 - Erased 100000 elements (size 2800000 capacity 8388608) 0 s loop 2 - Erased 100000 elements (size 2700000 capacity 8388608) 0.01 s loop 3 - Erased 100000 elements (size 2600000 capacity 8388608) 0 s loop 4 - Erased 100000 elements (size 2500000 capacity 8388608) 0 s loop 5 - Erased 100000 elements (size 2400000 capacity 8388608) 0 s loop 6 - Erased 100000 elements (size 2300000 capacity 8388608) 0 s loop 7 - Erased 100000 elements (size 2200000 capacity 8388608) 0 s ...
This commit is contained in:
@ -56,15 +56,16 @@ int main(int argc, char *argv[])
|
||||
HashTbl<label, label, Hash<label> > map(2 * nSize);
|
||||
|
||||
Info<< "Constructed map of size: " << nSize
|
||||
<< " (size " << map.size() << " capacity " << map.capacity() << ") "
|
||||
<< " " << timer.cpuTimeIncrement() << " s\n\n";
|
||||
|
||||
for (label i = 0; i < nSize; i++)
|
||||
{
|
||||
map.insert(i, i);
|
||||
}
|
||||
Info<< "Inserted " << nSize << " elements: "
|
||||
<< timer.cpuTimeIncrement() << " s\n\n";
|
||||
|
||||
Info<< "Inserted " << nSize << " elements"
|
||||
<< " (size " << map.size() << " capacity " << map.capacity() << ") "
|
||||
<< timer.cpuTimeIncrement() << " s\n";
|
||||
|
||||
label elemI = 0;
|
||||
for (label iLoop = 0; iLoop < nLoops; iLoop++)
|
||||
@ -73,8 +74,9 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
map.erase(elemI++);
|
||||
}
|
||||
Info<< "loop " << iLoop << " - Erased " << nBase << " elements: "
|
||||
<< " " << timer.cpuTimeIncrement() << " s\n";
|
||||
Info<< "loop " << iLoop << " - Erased " << nBase << " elements"
|
||||
<< " (size " << map.size() << " capacity " << map.capacity() << ") "
|
||||
<< timer.cpuTimeIncrement() << " s\n";
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@ -346,55 +346,41 @@ bool Foam::HashTbl<T, Key, Hash>::erase(const iterator& cit)
|
||||
{
|
||||
if (cit.elmtPtr_) // note: endIter_ also has 0 elmtPtr_
|
||||
{
|
||||
iterator& it = const_cast<iterator&>(cit);
|
||||
|
||||
// Search element before elmtPtr_
|
||||
hashedEntry* prev = 0;
|
||||
|
||||
for (hashedEntry* ep = table_[it.hashIndex_]; ep; ep = ep->next_)
|
||||
for (hashedEntry* ep = table_[cit.hashIndex_]; ep; ep = ep->next_)
|
||||
{
|
||||
if (ep == it.elmtPtr_)
|
||||
if (ep == cit.elmtPtr_)
|
||||
{
|
||||
break;
|
||||
}
|
||||
prev = ep;
|
||||
}
|
||||
|
||||
// adjust iterator after erase
|
||||
iterator& iter = const_cast<iterator&>(cit);
|
||||
|
||||
if (prev)
|
||||
{
|
||||
// Have element before elmtPtr
|
||||
prev->next_ = it.elmtPtr_->next_;
|
||||
delete it.elmtPtr_;
|
||||
it.elmtPtr_ = prev;
|
||||
// has an element before elmtPtr - reposition to there
|
||||
prev->next_ = iter.elmtPtr_->next_;
|
||||
delete iter.elmtPtr_;
|
||||
iter.elmtPtr_ = prev;
|
||||
}
|
||||
else
|
||||
{
|
||||
// elmtPtr is first element on SLList
|
||||
table_[it.hashIndex_] = it.elmtPtr_->next_;
|
||||
delete it.elmtPtr_;
|
||||
// elmtPtr was first element on SLList
|
||||
table_[iter.hashIndex_] = iter.elmtPtr_->next_;
|
||||
delete iter.elmtPtr_;
|
||||
|
||||
// Search back for previous non-zero table entry
|
||||
while (--it.hashIndex_ >= 0 && !table_[it.hashIndex_])
|
||||
{}
|
||||
// assign an non-NULL value so it doesn't look like end()/cend()
|
||||
iter.elmtPtr_ = reinterpret_cast<hashedEntry*>(this);
|
||||
|
||||
if (it.hashIndex_ >= 0)
|
||||
{
|
||||
// In table entry search for last element
|
||||
it.elmtPtr_ = table_[it.hashIndex_];
|
||||
|
||||
while (it.elmtPtr_ && it.elmtPtr_->next_)
|
||||
{
|
||||
it.elmtPtr_ = it.elmtPtr_->next_;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// No previous found. Mark with special value which is
|
||||
// - not end()/cend()
|
||||
// - handled by operator++
|
||||
it.elmtPtr_ = reinterpret_cast<hashedEntry*>(this);
|
||||
it.hashIndex_ = -1;
|
||||
}
|
||||
// mark with special hashIndex value
|
||||
// to signal that it has been rewound
|
||||
// the next increment will bring it bach to the present location
|
||||
iter.hashIndex_ = -iter.hashIndex_ - 1;
|
||||
}
|
||||
|
||||
nElmts_--;
|
||||
@ -402,8 +388,8 @@ bool Foam::HashTbl<T, Key, Hash>::erase(const iterator& cit)
|
||||
# ifdef FULLDEBUG
|
||||
if (debug)
|
||||
{
|
||||
Info<< "HashTbl<T, Key, Hash>::erase(iterator&) : "
|
||||
<< "hashedEntry " << it.elmtPtr_->key_ << " removed.\n";
|
||||
Info<< "HashTbl<T, Key, Hash>::erase(const iterator&) : "
|
||||
<< "hashedEntry " << iter.elmtPtr_->key_ << " removed.\n";
|
||||
}
|
||||
# endif
|
||||
|
||||
|
||||
@ -178,6 +178,9 @@ public:
|
||||
|
||||
// Access
|
||||
|
||||
//- The size of the underlying table
|
||||
inline label capacity() const;
|
||||
|
||||
//- Return number of elements in table.
|
||||
inline label size() const;
|
||||
|
||||
|
||||
@ -55,6 +55,13 @@ Foam::HashTbl<T, Key, Hash>::hashKeyIndex(const Key& key) const
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline Foam::label Foam::HashTbl<T, Key, Hash>::capacity() const
|
||||
{
|
||||
return tableSize_;
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline Foam::label Foam::HashTbl<T, Key, Hash>::size() const
|
||||
{
|
||||
@ -256,15 +263,16 @@ inline
|
||||
typename Foam::HashTbl<T, Key, Hash>::iterator&
|
||||
Foam::HashTbl<T, Key, Hash>::iterator::operator++()
|
||||
{
|
||||
// Check for special value from erase. (sets hashIndex to -1)
|
||||
if (hashIndex_ >= 0)
|
||||
// Check for special value (from erase) - this indicates the previous bin
|
||||
if (hashIndex_ < 0)
|
||||
{
|
||||
hashIndex_ = -hashIndex_;
|
||||
}
|
||||
else if (elmtPtr_ && elmtPtr_->next_)
|
||||
{
|
||||
// Do we have additional elements on the SLList?
|
||||
if (elmtPtr_ && elmtPtr_->next_)
|
||||
{
|
||||
elmtPtr_ = elmtPtr_->next_;
|
||||
return *this;
|
||||
}
|
||||
elmtPtr_ = elmtPtr_->next_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Step to the next table entry
|
||||
@ -275,9 +283,9 @@ Foam::HashTbl<T, Key, Hash>::iterator::operator++()
|
||||
)
|
||||
{}
|
||||
|
||||
if (hashIndex_ == hashTable_.tableSize_)
|
||||
if (hashIndex_ >= hashTable_.tableSize_)
|
||||
{
|
||||
// make end iterator
|
||||
// make an end iterator
|
||||
elmtPtr_ = 0;
|
||||
hashIndex_ = 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user