From 5dbf1f6bd64298f5091d6b94f2020c34f8297666 Mon Sep 17 00:00:00 2001 From: John Sully Date: Wed, 18 May 2022 20:00:14 +0000 Subject: [PATCH] Fix O(n^2) algorithm in the GC cleanup logic --- src/gc.h | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/src/gc.h b/src/gc.h index 8ed834ae9..b60c562a3 100644 --- a/src/gc.h +++ b/src/gc.h @@ -2,6 +2,7 @@ #include #include #include +#include struct ICollectable { @@ -45,14 +46,14 @@ public: void shutdown() { std::unique_lock lock(m_lock); - m_vecepochs.clear(); + m_listepochs.clear(); m_setepochOutstanding.clear(); } bool empty() const { std::unique_lock lock(m_lock); - return m_vecepochs.empty(); + return m_listepochs.empty(); } void endEpoch(uint64_t epoch, bool fNoFree = false) @@ -63,12 +64,12 @@ public: m_setepochOutstanding.erase(epoch); if (fNoFree) return; - std::vector vecclean; + std::list listclean; // No outstanding epochs? if (m_setepochOutstanding.empty()) { - vecclean = std::move(m_vecepochs); // Everything goes! + listclean = std::move(m_listepochs); // Everything goes! } else { @@ -77,18 +78,20 @@ public: return; // No available epochs to free // Clean any epochs available (after the lock) - for (size_t iepoch = 0; iepoch < m_vecepochs.size(); ++iepoch) + for (auto itr = m_listepochs.begin(); itr != m_listepochs.end(); /* itr incremented in loop*/) { - auto &e = m_vecepochs[iepoch]; + auto &e = *itr; + auto itrNext = itr; + ++itrNext; if (e < minepoch) { - vecclean.emplace_back(std::move(e)); - m_vecepochs.erase(m_vecepochs.begin() + iepoch); - --iepoch; + listclean.emplace_back(std::move(e)); + m_listepochs.erase(itr); } + itr = itrNext; } - assert(vecclean.empty() || fMinElement); + assert(listclean.empty() || fMinElement); } lock.unlock(); // don't hold it for the potentially long delete of vecclean @@ -100,13 +103,13 @@ public: serverAssert(m_setepochOutstanding.find(epoch) != m_setepochOutstanding.end()); serverAssert(sp->FWillFreeChildDebug() == false); - auto itr = std::find(m_vecepochs.begin(), m_vecepochs.end(), m_epochNext+1); - if (itr == m_vecepochs.end()) + auto itr = std::find(m_listepochs.begin(), m_listepochs.end(), m_epochNext+1); + if (itr == m_listepochs.end()) { EpochHolder e; e.tstamp = m_epochNext+1; e.m_vecObjs.push_back(std::move(sp)); - m_vecepochs.emplace_back(std::move(e)); + m_listepochs.emplace_back(std::move(e)); } else { @@ -117,7 +120,7 @@ public: private: mutable fastlock m_lock { "Garbage Collector"}; - std::vector m_vecepochs; + std::list m_listepochs; std::unordered_set m_setepochOutstanding; uint64_t m_epochNext = 0; }; \ No newline at end of file