# HG changeset patch # User Teemu Piippo # Date 1646823710 -7200 # Node ID 8a3047468994cd6b114133be13c6c19fdbe3a0c1 # Parent 50f055543ff66236bd24619576cb4451c8633d39 Fix performance issues in Model::find diff -r 50f055543ff6 -r 8a3047468994 src/model.cpp --- 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(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(); } } diff -r 50f055543ff6 -r 8a3047468994 src/model.h --- 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 body; - std::map objectsById; + mutable std::map 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(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{pointer->id.value}; } @@ -110,7 +111,7 @@ Q_EMIT beginInsertRows({}, position, position); this->body.insert(std::begin(this->body) + position, std::make_unique(args...)); ldraw::Object* pointer = this->body[position].get(); - this->objectsById[pointer->id] = pointer; + this->objectsById[pointer->id] = position; Q_EMIT endInsertRows(); return ldraw::Id{pointer->id.value}; }