From 2c73afb6ecd681a6a6030e943dfc1d87384f2056 Mon Sep 17 00:00:00 2001 From: Mark Olesen Date: Fri, 30 Oct 2009 18:54:51 +0100 Subject: [PATCH] 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 ... --- applications/test/HashTable3/hashTableTest3.C | 12 +++-- .../containers/HashTables/HashTbl/HashTbl.C | 54 +++++++------------ .../containers/HashTables/HashTbl/HashTbl.H | 3 ++ .../containers/HashTables/HashTbl/HashTblI.H | 26 +++++---- 4 files changed, 47 insertions(+), 48 deletions(-) diff --git a/applications/test/HashTable3/hashTableTest3.C b/applications/test/HashTable3/hashTableTest3.C index 422e35696c..f8d26caf06 100644 --- a/applications/test/HashTable3/hashTableTest3.C +++ b/applications/test/HashTable3/hashTableTest3.C @@ -56,15 +56,16 @@ int main(int argc, char *argv[]) HashTbl > 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; diff --git a/src/OpenFOAM/containers/HashTables/HashTbl/HashTbl.C b/src/OpenFOAM/containers/HashTables/HashTbl/HashTbl.C index 8e7be6b147..861f93df11 100644 --- a/src/OpenFOAM/containers/HashTables/HashTbl/HashTbl.C +++ b/src/OpenFOAM/containers/HashTables/HashTbl/HashTbl.C @@ -346,55 +346,41 @@ bool Foam::HashTbl::erase(const iterator& cit) { if (cit.elmtPtr_) // note: endIter_ also has 0 elmtPtr_ { - iterator& it = const_cast(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(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(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(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::erase(const iterator& cit) # ifdef FULLDEBUG if (debug) { - Info<< "HashTbl::erase(iterator&) : " - << "hashedEntry " << it.elmtPtr_->key_ << " removed.\n"; + Info<< "HashTbl::erase(const iterator&) : " + << "hashedEntry " << iter.elmtPtr_->key_ << " removed.\n"; } # endif diff --git a/src/OpenFOAM/containers/HashTables/HashTbl/HashTbl.H b/src/OpenFOAM/containers/HashTables/HashTbl/HashTbl.H index 1c9f6db257..877f8a1370 100644 --- a/src/OpenFOAM/containers/HashTables/HashTbl/HashTbl.H +++ b/src/OpenFOAM/containers/HashTables/HashTbl/HashTbl.H @@ -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; diff --git a/src/OpenFOAM/containers/HashTables/HashTbl/HashTblI.H b/src/OpenFOAM/containers/HashTables/HashTbl/HashTblI.H index 8dd27700b5..579e5553fb 100644 --- a/src/OpenFOAM/containers/HashTables/HashTbl/HashTblI.H +++ b/src/OpenFOAM/containers/HashTables/HashTbl/HashTblI.H @@ -55,6 +55,13 @@ Foam::HashTbl::hashKeyIndex(const Key& key) const // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // +template +inline Foam::label Foam::HashTbl::capacity() const +{ + return tableSize_; +} + + template inline Foam::label Foam::HashTbl::size() const { @@ -256,15 +263,16 @@ inline typename Foam::HashTbl::iterator& Foam::HashTbl::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::iterator::operator++() ) {} - if (hashIndex_ == hashTable_.tableSize_) + if (hashIndex_ >= hashTable_.tableSize_) { - // make end iterator + // make an end iterator elmtPtr_ = 0; hashIndex_ = 0; }