Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve Scene Tree editor performance #99700

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

hpvb
Copy link
Member

@hpvb hpvb commented Nov 26, 2024

We now cache the Node*<>TreeItem* mapping in the SceneTreeEditor. This allows us to make targeted updates to the Tree used to display the scene tree in the editor.

Previously on almost all changes to the scene tree the editor would rebuild the entire widget, causing a large number of deallocations an allocations. We now carefully manipulate the Tree widget in-situ saving a large number of these allocations.

There is definitely more that could be done, but this is already a massive improvement.

This fixes #83460

@hpvb hpvb added topic:editor performance cherrypick:4.3 Considered for cherry-picking into a future 4.3.x release labels Nov 26, 2024
@hpvb hpvb requested review from a team as code owners November 26, 2024 01:39
@hpvb
Copy link
Member Author

hpvb commented Nov 26, 2024

Before: (this scene has about 15,000 nodes)

Screencast.From.2024-11-26.02-11-22.mp4

After:

Screencast.From.2024-11-26.02-10-35.mp4

Copy link
Contributor

@arkology arkology left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stealing @AThousandShips 's job 🤣

editor/gui/scene_tree_editor.cpp Outdated Show resolved Hide resolved
editor/gui/scene_tree_editor.cpp Outdated Show resolved Hide resolved
editor/gui/scene_tree_editor.cpp Outdated Show resolved Hide resolved
editor/gui/scene_tree_editor.cpp Outdated Show resolved Hide resolved
@AThousandShips AThousandShips added this to the 4.x milestone Nov 26, 2024
editor/gui/scene_tree_editor.h Outdated Show resolved Hide resolved
scene/gui/tree.cpp Show resolved Hide resolved
@hpvb hpvb force-pushed the scene_tree_editor_performance branch 2 times, most recently from 6aefc0b to 9a25be0 Compare November 26, 2024 12:03
@hpvb hpvb requested a review from a team as a code owner November 26, 2024 12:20
@hpvb hpvb force-pushed the scene_tree_editor_performance branch from 431094f to 05519d4 Compare November 26, 2024 12:29
Copy link
Contributor

@arkology arkology left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I confirm that birdies are in the nest (dots at the end of the comments)😃

@hpvb hpvb force-pushed the scene_tree_editor_performance branch from 05519d4 to d4d55d0 Compare November 26, 2024 13:20
@KoBeWi
Copy link
Member

KoBeWi commented Nov 26, 2024

Changing valid types does not update the nodes (they stay disabled/enabled).

Can be tested with this simple EditorScript:

extends EditorScript
func _run() -> void:
	EditorInterface.popup_node_selector(func(n): print(n), ["Node2D"])

Run it, then remove "Node2D" and run again. Nodes that didn't match originally will stay disabled.

@hpvb hpvb force-pushed the scene_tree_editor_performance branch 2 times, most recently from c5fca34 to e076f60 Compare November 26, 2024 16:15
@hpvb

This comment was marked as outdated.

doc/classes/TreeItem.xml Outdated Show resolved Hide resolved
@hpvb hpvb force-pushed the scene_tree_editor_performance branch from e076f60 to 8851ae1 Compare November 26, 2024 17:18
@KoBeWi
Copy link
Member

KoBeWi commented Nov 26, 2024

The buttons don't get updated on various actions, including toggling unique name, making instance local, changing configuration warnings, adding node to group, connecting etc. The tooltip also doesn't update.
In case of making instance local, if you undo this operation, the nodes from the instance will incorrectly remain in the tree.

@hpvb
Copy link
Member Author

hpvb commented Nov 27, 2024

@KoBeWi okay I changed the design entirely. The cache now uses a custom hashing function to keep track of changes, this should be easier to keep consistent. This is a smidge slower than the previous way of doing it but still way faster than what we had.

I have tested the following:

  • Toggling unique names / undo
  • Make local / undo
  • Configuration warning / solve warning / undo
  • Adding to group / undo / Adding to group while connected / undo
  • Connecting a signal / undo/ Connecting signal while in a group / undo
  • Editable children / undo
  • Reparenting node / undo
  • Reordering node / undo
  • Change editor theme / and back
  • popup_node_selector (your test case)

@hpvb hpvb force-pushed the scene_tree_editor_performance branch from e113a71 to 1df8248 Compare November 27, 2024 12:10
@hpvb hpvb requested a review from arkology November 27, 2024 12:12
@KoBeWi
Copy link
Member

KoBeWi commented Nov 27, 2024

  • Make Local does not update icon. Also the node still has scene path in tooltip.
godot.windows.editor.dev.x86_64_HHOrYYEJ18.mp4
  • Editable children lose color once you add a node.
godot.windows.editor.dev.x86_64_2lyvNQzXzb.mp4
  • Attaching/removing the script does not update the icon (it was updating when I tested previously).
godot.windows.editor.dev.x86_64_5cxcUDaMEk.mp4
  • Lock/Group icons don't update in scene tree when they are toggled.

image

  • Same with AnimationPlayer's pin.
    image

  • Inherited scenes don't show their child nodes in yellow.

  • Changing Node's process_mode to disabled does not make the sub-tree gray.

  • When using Reparent... option, the reparented nodes in the dialog should appear red, but they don't.

@hpvb hpvb force-pushed the scene_tree_editor_performance branch 3 times, most recently from 9a856ff to 8d7b5eb Compare November 28, 2024 01:18
@hpvb
Copy link
Member Author

hpvb commented Nov 28, 2024

@KoBeWi I think I addressed your issues. Part of the reason I didn't figure it out was that there's a bug in master already whereby in the reparent node dialog nodes with disabled processing wouldn't show up as red. This is also fixed in this PR now.

The following things were tested:

old tests:

  • Toggling unique names / undo
  • Make local / undo
  • Configuration warning / solve warning / undo
  • Adding to group / undo / Adding to group while connected / undo
  • Connecting a signal / undo/ Connecting signal while in a group / undo
  • Editable children / undo
  • Reparenting node / undo
  • Reordering node / undo
  • Change editor theme / and back
  • popup_node_selector (your test case)

new tests:

  • Reparenting node via dialog, verified the colors and behavior against master
  • Creating connections via connections dialog, verified colors and behavior against master
  • Adding a script / undo
  • Make local / undo (verify icon/tooltip state)
  • Create new node in an "editable children" scene, verify colors match master
  • Toggle lock/unlock/undo, verify that lock icon appears in the scene tree
  • Verify that AnimationPlayer pin matches behavior on master
  • Set a node process mode / undo
  • Toggle unique name / undo
  • Reparent node via dialog, with the nodes having processing disabled. Verify that they still turn red (unlike on master)
  • Reparent node, cancel out of dialog, reparent a differnt node, validate that nodes do not stay red

@KoBeWi
Copy link
Member

KoBeWi commented Nov 28, 2024

Found another bug with node selector.
Changing type now properly changes colors, but the nodes stay unselectable.

@KoBeWi
Copy link
Member

KoBeWi commented Nov 28, 2024

I checked the implementation and looks like the main idea is hashing everything relevant for node appearance and using it to update only when needed. This means that every time we add something new that can affect anything about TreeItems we need to add it to the hash; rather error-prone, but the improved performance makes this compromise reasonable.
Though there are still some properties tracked outside of the hash. I wonder if they could be included too.

There are still a couple of bugged cases, but other than that I think the PR is fine overall.

@hpvb
Copy link
Member Author

hpvb commented Nov 28, 2024

I checked the implementation and looks like the main idea is hashing everything relevant for node appearance and using it to update only when needed. This means that every time we add something new that can affect anything about TreeItems we need to add it to the hash; rather error-prone, but the improved performance makes this compromise reasonable. Though there are still some properties tracked outside of the hash. I wonder if they could be included too.

As for changing the hash, I agree that it is a bit more work but on the other hand, for new things added it not showing up in the editor should be immediately apparent, unlike now where we are adding it now.

The things checked outside of the hash are things that are related to the editor state, not the node state. I didn't want to have to pass variables into the _hash_node() method. I could make it work that way if you'd like? It'd be pretty much the same amount of code.

For the pre_filter_color, that cannot be part of the hash as it is something that happens after nodes are updated and is also purely editor state.

There are still a couple of bugged cases, but other than that I think the PR is fine overall.

  • Nodes stay unselectable in the filter screen after changing the node type
  • Renaming a group doesn't get reflected on the tooltip

I think that is all you found this round, right?

@KoBeWi
Copy link
Member

KoBeWi commented Nov 28, 2024

Yes, last time I just checked all code that sets custom color or adds buttons, but there are other ways how TreeItems can be changed. There might be some tooltip changes I missed.

The things checked outside of the hash are things that are related to the editor state, not the node state. I didn't want to have to pass variables into the _hash_node() method. I could make it work that way if you'd like?

If you need to pass more than TreeItem then it's not worth it.

@hpvb
Copy link
Member Author

hpvb commented Nov 28, 2024

Yes, last time I just checked all code that sets custom color or adds buttons, but there are other ways how TreeItems can be changed. There might be some tooltip changes I missed.

The things checked outside of the hash are things that are related to the editor state, not the node state. I didn't want to have to pass variables into the _hash_node() method. I could make it work that way if you'd like?

I'll go through _update_tooltip with a fine-tooth comb to make sure I have indeed caught everything.

If you need to pass more than TreeItem then it's not worth it.

I would have to, yes. I'll leave it as-is then.

@hpvb hpvb force-pushed the scene_tree_editor_performance branch 2 times, most recently from c3a3a60 to 3c006fe Compare November 29, 2024 22:56
@hpvb
Copy link
Member Author

hpvb commented Nov 29, 2024

@KoBeWi I think I addressed your concerns and fixed the remaining bugs. I've also made the hash function smaller by relying on signals to update some aspects of the editor. These signals get emitted by Node itself, they must also be emitted if a script changes them. This claws back quite a lot of performance compared to the original non-hash based version.

Please be aware that quite a bit changed compared to last time!

The following things were tested:

  • Rename node / undo
  • Toggling unique names / undo
  • Make local / undo (verify icon/tooltip state)
  • Configuration warning / solve warning / undo
  • Adding to group / undo / Adding to group while connected / undo
  • Connecting a signal / undo/ Connecting signal while in a group / undo
  • Editable children / undo (verify color)
  • Create new node in an "editable children" scene, verify colors match master
  • Reparenting node / undo
  • Reparenting node via dialog, verified the colors and behavior against master
  • Reordering node / undo
  • Change editor theme / and back
  • popup_node_selector (your test case) Make sure that node selectability is updated appropriately
  • Creating connections via connections dialog, verified colors and behavior against master
  • Adding a script / undo
  • Toggle lock/unlock/undo, verify that lock icon appears in the scene tree
  • Verify that AnimationPlayer pin matches behavior on master
  • Set a node process mode / undo
  • Reparent node, cancel out of dialog, reparent a differnt node, validate that nodes do not stay red

new tests:

  • Change editor description, verify that tooltip changes.
  • Change group name group name does not change, this matches master behavior.
  • Create CollisonShape outside of a Body, move it into the body, verify that warnings clear.
  • Open connect dialog, close, add script to node, open, close, remove script from node, open,close verify that everything updates correctly.
  • Change type of node with children, ensure that that all warnings update correctly upwards and downwards in the tree.

We now cache the Node*<>TreeItem* mapping in the SceneTreeEditor. This
allows us to make targeted updates to the Tree used to display the scene
tree in the editor.

Previously on almost all changes to the scene tree the editor would
rebuild the entire widget, causing a large number of deallocations an
allocations. We now carefully manipulate the Tree widget in-situ saving
a large number of these allocations.

There is definitely more that could be done, but this is already a
massive improvement.

This fixes godotengine#83460
Since this function now exists there seems to be little reason not to
expose it. Discussed with @bruvzg.
@hpvb hpvb force-pushed the scene_tree_editor_performance branch from 3c006fe to 3dc7dea Compare November 29, 2024 23:43
@hpvb
Copy link
Member Author

hpvb commented Nov 30, 2024

I think I see a couple more ways to optimize things a bit further. I'll make more changes, sorry for the extra noise.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cherrypick:4.3 Considered for cherry-picking into a future 4.3.x release performance topic:editor
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Manipulating the scene tree gets progressively slower with more nodes added to the tree in the editor.
7 participants