Bladeren bron

Massive speed up on deleting nodes, fixes #18673
Also makes the editor exit faster

Juan Linietsky 7 jaren geleden
bovenliggende
commit
2d6b994e47
3 gewijzigde bestanden met toevoegingen van 47 en 31 verwijderingen
  1. 13 13
      core/object.cpp
  2. 11 10
      core/vmap.h
  3. 23 8
      scene/main/node.cpp

+ 13 - 13
core/object.cpp

@@ -1941,30 +1941,30 @@ Object::~Object() {
 		memdelete(script_instance);
 		memdelete(script_instance);
 	script_instance = NULL;
 	script_instance = NULL;
 
 
-	List<Connection> sconnections;
 	const StringName *S = NULL;
 	const StringName *S = NULL;
 
 
-	while ((S = signal_map.next(S))) {
+	while ((S = signal_map.next(NULL))) {
 
 
 		Signal *s = &signal_map[*S];
 		Signal *s = &signal_map[*S];
 
 
-		ERR_EXPLAIN("Attempt to delete an object in the middle of a signal emission from it");
-		ERR_CONTINUE(s->lock > 0);
-
-		for (int i = 0; i < s->slot_map.size(); i++) {
-
-			sconnections.push_back(s->slot_map.getv(i).conn);
+		if (s->lock) {
+			ERR_EXPLAIN("Attempt to delete an object in the middle of a signal emission from it");
+			ERR_CONTINUE(s->lock > 0);
 		}
 		}
-	}
 
 
-	for (List<Connection>::Element *E = sconnections.front(); E; E = E->next()) {
+		//brute force disconnect for performance
+		int slot_count = s->slot_map.size();
+		const VMap<Signal::Target, Signal::Slot>::Pair *slot_list = s->slot_map.get_array();
 
 
-		Connection &c = E->get();
-		ERR_CONTINUE(c.source != this); //bug?
+		for (int i = 0; i < slot_count; i++) {
+
+			slot_list[i].value.conn.target->connections.erase(slot_list[i].value.cE);
+		}
 
 
-		this->_disconnect(c.signal, c.target, c.method, true);
+		signal_map.erase(*S);
 	}
 	}
 
 
+	//signals from nodes that connect to this node
 	while (connections.size()) {
 	while (connections.size()) {
 
 
 		Connection c = connections.front()->get();
 		Connection c = connections.front()->get();

+ 11 - 10
core/vmap.h

@@ -36,22 +36,23 @@
 
 
 template <class T, class V>
 template <class T, class V>
 class VMap {
 class VMap {
-
-	struct _Pair {
+public:
+	struct Pair {
 
 
 		T key;
 		T key;
 		V value;
 		V value;
 
 
-		_FORCE_INLINE_ _Pair() {}
+		_FORCE_INLINE_ Pair() {}
 
 
-		_FORCE_INLINE_ _Pair(const T &p_key, const V &p_value) {
+		_FORCE_INLINE_ Pair(const T &p_key, const V &p_value) {
 
 
 			key = p_key;
 			key = p_key;
 			value = p_value;
 			value = p_value;
 		}
 		}
 	};
 	};
 
 
-	CowData<_Pair> _cowdata;
+private:
+	CowData<Pair> _cowdata;
 
 
 	_FORCE_INLINE_ int _find(const T &p_val, bool &r_exact) const {
 	_FORCE_INLINE_ int _find(const T &p_val, bool &r_exact) const {
 
 
@@ -61,7 +62,7 @@ class VMap {
 
 
 		int low = 0;
 		int low = 0;
 		int high = _cowdata.size() - 1;
 		int high = _cowdata.size() - 1;
-		const _Pair *a = _cowdata.ptr();
+		const Pair *a = _cowdata.ptr();
 		int middle = 0;
 		int middle = 0;
 
 
 #if DEBUG_ENABLED
 #if DEBUG_ENABLED
@@ -95,7 +96,7 @@ class VMap {
 		int low = 0;
 		int low = 0;
 		int high = _cowdata.size() - 1;
 		int high = _cowdata.size() - 1;
 		int middle;
 		int middle;
-		const _Pair *a = _cowdata.ptr();
+		const Pair *a = _cowdata.ptr();
 
 
 		while (low <= high) {
 		while (low <= high) {
 			middle = (low + high) / 2;
 			middle = (low + high) / 2;
@@ -121,7 +122,7 @@ public:
 			_cowdata.get_m(pos).value = p_val;
 			_cowdata.get_m(pos).value = p_val;
 			return pos;
 			return pos;
 		}
 		}
-		_cowdata.insert(pos, _Pair(p_key, p_val));
+		_cowdata.insert(pos, Pair(p_key, p_val));
 		return pos;
 		return pos;
 	}
 	}
 
 
@@ -152,12 +153,12 @@ public:
 	_FORCE_INLINE_ int size() const { return _cowdata.size(); }
 	_FORCE_INLINE_ int size() const { return _cowdata.size(); }
 	_FORCE_INLINE_ bool empty() const { return _cowdata.empty(); }
 	_FORCE_INLINE_ bool empty() const { return _cowdata.empty(); }
 
 
-	const _Pair *get_array() const {
+	const Pair *get_array() const {
 
 
 		return _cowdata.ptr();
 		return _cowdata.ptr();
 	}
 	}
 
 
-	_Pair *get_array() {
+	Pair *get_array() {
 
 
 		return _cowdata.ptrw();
 		return _cowdata.ptrw();
 	}
 	}

+ 23 - 8
scene/main/node.cpp

@@ -157,7 +157,7 @@ void Node::_notification(int p_notification) {
 			// kill children as cleanly as possible
 			// kill children as cleanly as possible
 			while (data.children.size()) {
 			while (data.children.size()) {
 
 
-				Node *child = data.children[0];
+				Node *child = data.children[data.children.size() - 1]; //begin from the end because its faster and more consistent with creation
 				remove_child(child);
 				remove_child(child);
 				memdelete(child);
 				memdelete(child);
 			}
 			}
@@ -1182,13 +1182,24 @@ void Node::remove_child(Node *p_child) {
 		ERR_FAIL_COND(data.blocked > 0);
 		ERR_FAIL_COND(data.blocked > 0);
 	}
 	}
 
 
+	int child_count = data.children.size();
+	Node **children = data.children.ptrw();
 	int idx = -1;
 	int idx = -1;
-	for (int i = 0; i < data.children.size(); i++) {
 
 
-		if (data.children[i] == p_child) {
+	if (p_child->data.pos >= 0 && p_child->data.pos < child_count) {
+		if (children[p_child->data.pos] == p_child) {
+			idx = p_child->data.pos;
+		}
+	}
+
+	if (idx == -1) { //maybe removed while unparenting or something and index was not updated, so just in case the above fails, try this.
+		for (int i = 0; i < child_count; i++) {
 
 
-			idx = i;
-			break;
+			if (children[i] == p_child) {
+
+				idx = i;
+				break;
+			}
 		}
 		}
 	}
 	}
 
 
@@ -1205,10 +1216,14 @@ void Node::remove_child(Node *p_child) {
 
 
 	data.children.remove(idx);
 	data.children.remove(idx);
 
 
-	for (int i = idx; i < data.children.size(); i++) {
+	//update pointer and size
+	child_count = data.children.size();
+	children = data.children.ptrw();
 
 
-		data.children[i]->data.pos = i;
-		data.children[i]->notification(NOTIFICATION_MOVED_IN_PARENT);
+	for (int i = idx; i < child_count; i++) {
+
+		children[i]->data.pos = i;
+		children[i]->notification(NOTIFICATION_MOVED_IN_PARENT);
 	}
 	}
 
 
 	p_child->data.parent = NULL;
 	p_child->data.parent = NULL;