godot icon indicating copy to clipboard operation
godot copied to clipboard

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

Open maidopi-usagi opened this issue 1 year ago • 9 comments

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?

  • Bugsquad edit, closes: https://github.com/godotengine/godot/issues/70869
  • Bugsquad edit, closes: https://github.com/godotengine/godot/issues/83460

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 avatar Sep 11 '24 06:09 maidopi-usagi

Oops, I think I messed up something in the commit, will commit again.

maidopi-usagi avatar Sep 11 '24 06:09 maidopi-usagi

@ALiwoto Please don't bump without contributing significant new information. Use the 👍 reaction button on the first post instead.

timothyqiu avatar Sep 12 '24 17:09 timothyqiu

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

scgm0 avatar Sep 12 '24 18:09 scgm0

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.

KoBeWi avatar Sep 13 '24 20:09 KoBeWi

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?

https://github.com/godotengine/godot/blob/f5f813e9674fa433a9702ea614bcd56e59dd80db/scene/gui/tree.cpp#L1824-L1827

https://github.com/godotengine/godot/blob/f5f813e9674fa433a9702ea614bcd56e59dd80db/scene/gui/tree.cpp#L1523-L1525

maidopi-usagi avatar Sep 14 '24 13:09 maidopi-usagi

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

scgm0 avatar Oct 04 '24 13:10 scgm0

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 avatar Oct 05 '24 23:10 KoBeWi

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

KoBeWi avatar Oct 05 '24 23:10 KoBeWi

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. https://github.com/godotengine/godot/blob/f5f813e9674fa433a9702ea614bcd56e59dd80db/scene/gui/tree.cpp#L1542-L1552

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 avatar Oct 06 '24 11:10 maidopi-usagi

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.

KoBeWi avatar Nov 06 '24 10:11 KoBeWi

Thanks!

Repiteo avatar Nov 10 '24 18:11 Repiteo