Wed, 09 Mar 2022 13:01:50 +0200
Fix performance issues in Model::find
src/model.cpp | file | annotate | diff | comparison | revisions | |
src/model.h | file | annotate | diff | comparison | revisions |
--- a/src/model.cpp Wed Mar 09 12:42:45 2022 +0200 +++ b/src/model.cpp Wed Mar 09 13:01:50 2022 +0200 @@ -101,15 +101,24 @@ */ QModelIndex Model::find(ldraw::id_t id) const { - // FIXME: This linear search will probably cause performance issues - for (std::size_t i = 0; i < this->body.size(); i += 1) + if (this->needObjectsByIdRebuild) { - if (this->body[i]->id == id) + this->objectsById.clear(); + for (std::size_t i = 0; i < this->body.size(); ++i) { - return this->index(static_cast<int>(i)); + this->objectsById[this->body[i]->id] = i; } + this->needObjectsByIdRebuild = false; } - return {}; + const auto it = this->objectsById.find(id); + if (it != this->objectsById.end()) + { + return this->index(it->second); + } + else + { + return {}; + } } /** @@ -159,7 +168,7 @@ this->body.push_back(std::move(object)); Q_EMIT this->endInsertRows(); const ldraw::id_t id = this->body.back()->id; - this->objectsById[id] = this->body.back().get(); + this->objectsById[id] = this->body.size() - 1; return id; } @@ -173,6 +182,7 @@ { Q_EMIT this->beginRemoveRows({}, position, position); this->body.erase(std::begin(this->body) + position); + this->needObjectsByIdRebuild = true; Q_EMIT this->endRemoveRows(); } }
--- a/src/model.h Wed Mar 09 12:42:45 2022 +0200 +++ b/src/model.h Wed Mar 09 13:01:50 2022 +0200 @@ -68,7 +68,8 @@ private: bool modified = false; std::vector<ModelObjectPointer> body; - std::map<ldraw::id_t, ldraw::Object*> objectsById; + mutable std::map<ldraw::id_t, std::size_t> objectsById; + mutable bool needObjectsByIdRebuild = false; }; void save(const Model& model, QIODevice *device); @@ -99,7 +100,7 @@ Q_EMIT beginInsertRows({}, position, position); this->body.push_back(std::make_unique<T>(args...)); ldraw::Object* pointer = this->body.back().get(); - this->objectsById[pointer->id] = pointer; + this->objectsById[pointer->id] = this->body.size() - 1; Q_EMIT endInsertRows(); return ldraw::Id<T>{pointer->id.value}; } @@ -110,7 +111,7 @@ Q_EMIT beginInsertRows({}, position, position); this->body.insert(std::begin(this->body) + position, std::make_unique<T>(args...)); ldraw::Object* pointer = this->body[position].get(); - this->objectsById[pointer->id] = pointer; + this->objectsById[pointer->id] = position; Q_EMIT endInsertRows(); return ldraw::Id<T>{pointer->id.value}; }