From 6ebef31b3c0c26ee1275eb3e0a6f0f21a7fef494 Mon Sep 17 00:00:00 2001 From: Ryan <73148864+Ryan-000@users.noreply.github.com> Date: Fri, 22 Aug 2025 23:02:51 -0400 Subject: [PATCH] Make Node::orphan_node_count thread-safe --- doc/classes/Performance.xml | 1 + main/performance.cpp | 12 +++++++++++- main/performance.h | 1 + scene/main/node.cpp | 16 +++++++++------- scene/main/node.h | 4 +++- 5 files changed, 25 insertions(+), 9 deletions(-) diff --git a/doc/classes/Performance.xml b/doc/classes/Performance.xml index 20f858e1e65..6925e3d70a8 100644 --- a/doc/classes/Performance.xml +++ b/doc/classes/Performance.xml @@ -154,6 +154,7 @@ Number of orphan nodes, i.e. nodes which are not parented to a node of the scene tree. [i]Lower is better.[/i] + [b]Note:[/b] This is only available in debug mode and will always return [code]0[/code] when used in a project exported in release mode. The total number of objects in the last rendered frame. This metric doesn't include culled objects (either via hiding nodes, frustum culling or occlusion culling). [i]Lower is better.[/i] diff --git a/main/performance.cpp b/main/performance.cpp index 8f0bedbde67..3c355d01e17 100644 --- a/main/performance.cpp +++ b/main/performance.cpp @@ -141,6 +141,16 @@ int Performance::_get_node_count() const { return sml->get_node_count(); } +int Performance::_get_orphan_node_count() const { +#ifdef DEBUG_ENABLED + const int total_node_count = Node::total_node_count.get(); + const int orphan_node_count = total_node_count - _get_node_count(); + return orphan_node_count; +#else + return 0; +#endif +} + String Performance::get_monitor_name(Monitor p_monitor) const { ERR_FAIL_INDEX_V(p_monitor, MONITOR_MAX, String()); static const char *names[MONITOR_MAX] = { @@ -240,7 +250,7 @@ double Performance::get_monitor(Monitor p_monitor) const { case OBJECT_NODE_COUNT: return _get_node_count(); case OBJECT_ORPHAN_NODE_COUNT: - return Node::orphan_node_count; + return _get_orphan_node_count(); case RENDER_TOTAL_OBJECTS_IN_FRAME: return RS::get_singleton()->get_rendering_info(RS::RENDERING_INFO_TOTAL_OBJECTS_IN_FRAME); case RENDER_TOTAL_PRIMITIVES_IN_FRAME: diff --git a/main/performance.h b/main/performance.h index 0fdac285cd7..cf822bbb706 100644 --- a/main/performance.h +++ b/main/performance.h @@ -46,6 +46,7 @@ class Performance : public Object { static void _bind_methods(); int _get_node_count() const; + int _get_orphan_node_count() const; double _process_time; double _physics_process_time; diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 9fe529155e5..a443033f420 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -44,7 +44,9 @@ #include "scene/resources/packed_scene.h" #include "viewport.h" -int Node::orphan_node_count = 0; +#ifdef DEBUG_ENABLED +SafeNumeric Node::total_node_count{ 0 }; +#endif thread_local Node *Node::current_process_thread_group = nullptr; @@ -165,7 +167,6 @@ void Node::_notification(int p_notification) { } data.tree->nodes_in_tree_count++; - orphan_node_count--; } break; @@ -193,7 +194,6 @@ void Node::_notification(int p_notification) { } data.tree->nodes_in_tree_count--; - orphan_node_count++; if (data.input) { remove_from_group("_vp_input" + itos(get_viewport()->get_instance_id())); @@ -4058,9 +4058,9 @@ String Node::_get_name_num_separator() { Node::Node() { _define_ancestry(AncestralClass::NODE); - - orphan_node_count++; - +#ifdef DEBUG_ENABLED + total_node_count.increment(); +#endif // Default member initializer for bitfield is a C++20 extension, so: data.process_mode = PROCESS_MODE_INHERIT; @@ -4107,7 +4107,9 @@ Node::~Node() { ERR_FAIL_COND(data.parent); ERR_FAIL_COND(data.children_cache.size()); - orphan_node_count--; +#ifdef DEBUG_ENABLED + total_node_count.decrement(); +#endif } //////////////////////////////// diff --git a/scene/main/node.h b/scene/main/node.h index 35562339ab0..43076f46b08 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -130,7 +130,9 @@ public: bool operator()(const Node *p_a, const Node *p_b) const { return p_b->is_greater_than(p_a); } }; - static int orphan_node_count; +#ifdef DEBUG_ENABLED + static SafeNumeric total_node_count; +#endif void _update_process(bool p_enable, bool p_for_children);