Fix performance issues in Model::find

Wed, 09 Mar 2022 13:01:50 +0200

author
Teemu Piippo <teemu@hecknology.net>
date
Wed, 09 Mar 2022 13:01:50 +0200
changeset 173
8a3047468994
parent 172
50f055543ff6
child 174
3016b494685c

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};
 }

mercurial