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

[Tree] Improve Tree Performance by replacing computed height with TreeItem's cached minimum size #96841

Merged
merged 1 commit into from
Nov 10, 2024

Conversation

maidopi-usagi
Copy link
Contributor

@maidopi-usagi maidopi-usagi commented Sep 11, 2024

Originally, TreeItem's content height was computed in every draw while traversing the tree, even if the item content never changes. And there's already minimum_size cached in each item, which is computed in a similar way.

Tested on a massive plain-tree with 15K and 150K items(project file attached below), and got significant performance improvement (About 5~10x).
Here're results on my desktop when scrolling to near the bottom of tree.

Amount This PR Master
15K Items 1543FPS 152FPS
150K Items 36FPS 3FPS, and with a lot much longer start time

I also checked the behaviors of more complex Trees in the editor, and didn't notice any obvious artifacts, but I'm not very sure if there were any side-effect after changing these.

Might partially fix these issues?

EDIT:
After some "extreme" test with huge amount of auto-wrapping text TreeItems and scrolling fast will cause some item's height cache being outdated.
I'm still looking for some other way to make this work. So convert this to draft now and will try reopen when I figured out.
I believe that's not related to this PR's modification, as I can reproduce the above issue in both 4.3 and master branch. I'll open another issue about that.

treetest.zip

@maidopi-usagi maidopi-usagi requested a review from a team as a code owner September 11, 2024 06:48
@maidopi-usagi

This comment was marked as outdated.

@maidopi-usagi maidopi-usagi force-pushed the tree_item_height_cache branch 2 times, most recently from 8cc112d to 437b4d2 Compare September 11, 2024 07:25
@AThousandShips AThousandShips added this to the 4.x milestone Sep 11, 2024
@maidopi-usagi maidopi-usagi marked this pull request as draft September 11, 2024 12:15
@timothyqiu

This comment was marked as off-topic.

@maidopi-usagi maidopi-usagi force-pushed the tree_item_height_cache branch 4 times, most recently from e5e11b2 to f5f813e Compare September 12, 2024 18:25
@maidopi-usagi maidopi-usagi marked this pull request as ready for review September 12, 2024 18:37
@scgm0
Copy link
Contributor

scgm0 commented Sep 12, 2024

After testing, it works great in my personal project, now I can directly use Tree to build my tools 👍
master:
图片
this pr:
图片

@KoBeWi
Copy link
Member

KoBeWi commented Sep 13, 2024

I see some discrepancy between the code you deleted in compute_item_height() and TreeItem's get_minimum_size(), e.g. the latter does not account for theme_cache.checked height.

@maidopi-usagi
Copy link
Contributor Author

maidopi-usagi commented Sep 14, 2024

I see some discrepancy between the code you deleted in compute_item_height() and TreeItem's get_minimum_size(), e.g. the latter does not account for theme_cache.checked height.

I'm wondering the reason that get_minimum_size() didn't take theme_cache.checked's height into account. If there's nothing affected I'll re-add that into the method.

Also I noticed that update_item_cell() seems to be called twice every time (another in get_minimum_size()).
Maybe we can remove the following one?

godot/scene/gui/tree.cpp

Lines 1824 to 1827 in f5f813e

for (int i = 0; i < columns.size(); i++) {
if (p_item->cells[i].dirty) {
const_cast<Tree *>(this)->update_item_cell(p_item, i);
}

godot/scene/gui/tree.cpp

Lines 1523 to 1525 in f5f813e

if (cell.dirty) {
parent_tree->update_item_cell(this, p_column);
}

@scgm0
Copy link
Contributor

scgm0 commented Oct 4, 2024

This PR is working fine in my project, what's causing it not to be merged yet?

@KoBeWi
Copy link
Member

KoBeWi commented Oct 5, 2024

Also I noticed that update_item_cell() seems to be called twice every time (another in get_minimum_size()).

Only once call will be effective, unless the cell becomes dirty again for some reason.

KoBeWi
KoBeWi previously approved these changes Oct 5, 2024
@KoBeWi KoBeWi dismissed their stale review October 5, 2024 23:05

actually I just noticed a bug

@KoBeWi
Copy link
Member

KoBeWi commented Oct 5, 2024

The scene tree is noticeably bigger vertically. The left is with this PR, the right is without:
image

@maidopi-usagi
Copy link
Contributor Author

maidopi-usagi commented Oct 6, 2024

The scene tree is noticeably bigger vertically. The left is with this PR, the right is without: image

Thanks for pointing out!
I've found that's because of the cached minimum size computes buttons height using the combination of button texture's size and button_pressed's minimum_size, compared with the old calculation method.

godot/scene/gui/tree.cpp

Lines 1542 to 1552 in f5f813e

// Buttons.
for (int i = 0; i < cell.buttons.size(); i++) {
Ref<Texture2D> texture = cell.buttons[i].texture;
if (texture.is_valid()) {
Size2 button_size = texture->get_size() + parent_tree->theme_cache.button_pressed->get_minimum_size();
size.width += button_size.width + parent_tree->theme_cache.button_margin;
size.height = MAX(size.height, button_size.height);
}
}

As cached minimum size was used only for width calculation before this PR, I'm keeping the width combination here.
To match the original Tree::compute_item_height's implementation, I just discard the height of button button_pressed's minimum size. Or should it use the maximum height instead?

image

@maidopi-usagi maidopi-usagi force-pushed the tree_item_height_cache branch from bd51ae2 to 75c2b0b Compare October 6, 2024 11:46
@maidopi-usagi maidopi-usagi requested a review from KoBeWi October 6, 2024 12:42
@KoBeWi
Copy link
Member

KoBeWi commented Nov 6, 2024

Or should it use the maximum height instead?

There is some weird behavior when button_pressed is bigger than other styles, but it's the same as the one on master, so I think it's fine.

Copy link
Member

@KoBeWi KoBeWi left a comment

Choose a reason for hiding this comment

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

Needs rebase.

@maidopi-usagi maidopi-usagi force-pushed the tree_item_height_cache branch from 79b994c to 07b7af0 Compare November 6, 2024 19:28
@clayjohn clayjohn modified the milestones: 4.x, 4.4 Nov 7, 2024
@Repiteo Repiteo merged commit 1cad552 into godotengine:master Nov 10, 2024
20 checks passed
@Repiteo
Copy link
Contributor

Repiteo commented Nov 10, 2024

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Poor performance of 2D Tree View with many items
7 participants