Use LocalVector
for Node3D
and CanvasItem
children
#107481
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Node3D
maintains its own list ofNode3D
-only children (separate from theNode
), in order to (in theory) make child iteration faster for only node3d children. The same happens withCanvasItem
andCanvasItem
children.The problem is that these lists are stored as a linked list, and there is no reason to require linked list. Linked lists are bad for cache.
Forward port of #107480
Benchmark
(See 3.x PR, but gains should be similar in 4.x)
before: 157 fps
after: 280 fps
The benchmark creates a large number of
Node3D
children to the root node, then rotates the root. This stresses the_propagate_transform_changed()
which utilizes the children list.Notes
Node3D
children list entirely and utilizing theNode
children list instead with fast casting, but this PR is still faster (because of no need for cast checks).NULL
checks in the original were redundant, I don't think these pointers can beNULL
given the code here.SceneTreeFTI
now it is faster, instead ofNode
children. Not 100% on this yet, but worth looking into.CanvasItem
, the same applies.Additional
These lists are similar in 3.x and 4.x. Unlike the
Node
children list, they are unordered, so no need to change when rearranging children, only when entering / exiting tree, and removing items is O(1) rather than O(N).Instead of relying on the ability of linked list to remove an element fast, we use
remove_at_unordered
to remove elements in O(1). With linear lists, and keeping an ID of which child we are in the parent list, we have to rejig the child that is moved duringremove_at_unordered()
, and reassign its child ID. That should be the only thing required to keep the IDs in sync.