From f81be5b4639b6b17d7c8874addd8a7fdb9206663 Mon Sep 17 00:00:00 2001 From: CedricMocquillon Date: Thu, 13 May 2021 19:59:28 +0200 Subject: [PATCH] Replace land static container from vector to flat_set I use a ordered container to fix the "is there any other way to speed this up?". The flat_set allow to have the same locality when searching an element. I use the is_transparent C++14 feature to avoid to create a dummy Land when searching I use a unique_ptr to avoid to manualy manage the memory --- apps/openmw/mwworld/store.cpp | 48 +++-------------------------------- apps/openmw/mwworld/store.hpp | 34 ++++++++++++++++++++++--- 2 files changed, 34 insertions(+), 48 deletions(-) diff --git a/apps/openmw/mwworld/store.cpp b/apps/openmw/mwworld/store.cpp index fb66b0a1d7..d2c4725117 100644 --- a/apps/openmw/mwworld/store.cpp +++ b/apps/openmw/mwworld/store.cpp @@ -11,25 +11,6 @@ #include #include -namespace -{ - struct Compare - { - bool operator()(const ESM::Land *x, const ESM::Land *y) { - if (x->mX == y->mX) { - return x->mY < y->mY; - } - return x->mX < y->mX; - } - bool operator()(const ESM::Land *x, const std::pair& y) { - if (x->mX == y.first) { - return x->mY < y.second; - } - return x->mX < y.first; - } - }; -} - namespace MWWorld { RecordId::RecordId(const std::string &id, bool isDeleted) @@ -425,11 +406,6 @@ namespace MWWorld //========================================================================= Store::~Store() { - for (const ESM::Land* staticLand : mStatic) - { - delete staticLand; - } - } size_t Store::getSize() const { @@ -446,12 +422,8 @@ namespace MWWorld const ESM::Land *Store::search(int x, int y) const { std::pair comp(x,y); - - std::vector::const_iterator it = - std::lower_bound(mStatic.begin(), mStatic.end(), comp, Compare()); - - if (it != mStatic.end() && (*it)->mX == x && (*it)->mY == y) { - return *it; + if (auto it = mStatic.find(comp); it != mStatic.end() && (*it)->mX == x && (*it)->mY == y) { + return it->get(); } return nullptr; } @@ -467,24 +439,13 @@ namespace MWWorld } RecordId Store::load(ESM::ESMReader &esm) { - ESM::Land *ptr = new ESM::Land(); + auto ptr = std::make_unique(); bool isDeleted = false; ptr->load(esm, isDeleted); // Same area defined in multiple plugins? -> last plugin wins - // Can't use search() because we aren't sorted yet - is there any other way to speed this up? - for (std::vector::iterator it = mStatic.begin(); it != mStatic.end(); ++it) - { - if ((*it)->mX == ptr->mX && (*it)->mY == ptr->mY) - { - delete *it; - mStatic.erase(it); - break; - } - } - - mStatic.push_back(ptr); + mStatic.insert(std::move(ptr)); return RecordId("", isDeleted); } @@ -494,7 +455,6 @@ namespace MWWorld if (mBuilt) return; - std::sort(mStatic.begin(), mStatic.end(), Compare()); mBuilt = true; } diff --git a/apps/openmw/mwworld/store.hpp b/apps/openmw/mwworld/store.hpp index e37152431e..d65422516a 100644 --- a/apps/openmw/mwworld/store.hpp +++ b/apps/openmw/mwworld/store.hpp @@ -3,7 +3,9 @@ #include #include +#include #include +#include #include "recordcmp.hpp" @@ -74,10 +76,10 @@ namespace MWWorld const T *find(int index) const; }; - template + template > class SharedIterator { - typedef typename std::vector::const_iterator Iter; + typedef typename Container::const_iterator Iter; Iter mIter; @@ -233,10 +235,34 @@ namespace MWWorld template <> class Store : public StoreBase { - std::vector mStatic; + struct SpatialComparator + { + using is_transparent = void; + + bool operator()(const std::unique_ptr& x, const std::unique_ptr& y) const { + if (x->mX == y->mX) { + return x->mY < y->mY; + } + return x->mX < y->mX; + } + bool operator()(const std::unique_ptr& x, const std::pair& y) const { + if (x->mX == y.first) { + return x->mY < y.second; + } + return x->mX < y.first; + } + bool operator()(const std::pair& x, const std::unique_ptr& y) const { + if (x.first == y->mX) { + return x.second < y->mY; + } + return x.first < y->mX; + } + }; + using Statics = boost::container::flat_set, SpatialComparator>; + Statics mStatic; public: - typedef SharedIterator iterator; + typedef SharedIterator iterator; virtual ~Store();