-
-
Notifications
You must be signed in to change notification settings - Fork 21.3k
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 pathfinding performance by using a heap to store traversable polygons #85965
Improve pathfinding performance by using a heap to store traversable polygons #85965
Conversation
d7a5370
to
692e851
Compare
692e851
to
29b2328
Compare
I realized that the current implementation doesn't take care of multithreading. I'm turning this PR back into a draft until I fix the problem. |
29b2328
to
ca2fd48
Compare
I changed the approach to be multithreading friendly. Pathfinding requests now leave
Since it's not possible anymore for the I added a multithreading test to the test project and also rebased on master (checked that #85238 is still fixed). I will squash the commits if nothing major comes out during the review. |
I suggest moving this heap to a navigation module internal class/struct instead of a core template. I talked with some core devs and there is a preference for a more "local" solution that does not touch core. That is also the primary hold-up for this pr. |
With the merge window for 4.4 now open I would like to get this in but it requires rebase and the mentioned move of the new heap class from core to the navigation module. I would suggest to move it to the nav_utils.h file in the gd namespace where everything else currently is that is used across the navsystem. If you are still around @ershn and want to do these changes for the PR appreciated, else just let me know and I will salvage the PR and give you credit. Either way thank you for doing the main work on this optimization and all the performance testing. |
4e23595
to
d3000d3
Compare
Sorry for the delay. I moved the heap class to Thank you for the review smix8 ! |
@Scony is usually the test maniac ... ;) EDIT @ershn I tested the rebased PR and while it works fine in the provided test project I am getting some random heap and polygon.id index crashes in other projects that use a NavigationAgent2D/3D or the NavigationPathQueryParameters2D/3D on ready.
The TileMap does a deferred setup so that may be why it works in the TileMap test project but crashes in other projects without TileMap? I tested both 2D and 3D and a new project, as soon as a NavigationAgent queries on the first frame it has like a 1 in 3 chance of causing the index crash with the get_path() function. Since the crash even reports the right polygon count something seem to stop the ids from being assigned or do they overflow? That some suspicious FLT_MAX error index. |
d3000d3
to
06e054a
Compare
Thank you for the tests ! The bug probably happened because the synthetic polygons generated for navigation links were not being taken care of during map sync. Their id was never updated from the default value of UINT32_MAX which resulted in invalid array accesses when trying to process them during pathfinding. This should be fixed now. Could you test again with your test scenes ?
Ok, I'll leave the tests there for the time being then. |
@ershn Yeah that was it, no more crashes or errors (so far 😝). I fear this PR might need another rebase soon as it will collide with the other PRs that are currently in the 4.4 merge queue depending on what gets merged first, brace for impact! |
tests/servers/test_navigation_heap.h
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd say this should be moved into the module as it, unlike the other tests, is module specific
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok. I moved it into tests/servers/test_navigation_server_3d.h
(like smix8 suggested) if that's what you meant.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I meant it should be moved to modules/navigation/tests
, but I think that's okay too
06e054a
to
c3ee32f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In my view, the heap implementation is generic enough so that should placed be within core/templates
. @smix8 who are the "core devs" that suggested otherwise?
If not core/templates
then I don's see a reason why this fairly-generic class wouldn't be placed in some separate file like modules/navigation/heap.h
or so. Same goes for tests - test_navigation_server_3d.h
which is actually a bunch of module tests is not a good place for heap unit tests. I'd at least extract it to tests/servers/test_navigation_server_3d_heap.h
and include in tests/servers/test_navigation-server_3d.h
.
That was when I asked reduz with 1-2 other core people around for a review on this PR months ago. They all said this should be local to the navigation module and not part of core which is why I made that comment back in April to unblock this PR. Sure it could be its own file, same for the tests, I don't mind either. Just don't want to drive ershn crazy with back and forth changes. We also could do the changes in a follow up PR if you want to reorganize some files. |
Ok, let's do the refactoring in the followup PR. |
@Scony See this. Currently it's used only by the navigation so adding to core is not justified. If something else will need it as well then it will probably be fine to move it to core. |
Thanks! |
Description
Improves pathfinding performance by doing 2 things.
SortArray
don't allow for that)Closes godotengine/godot-proposals#8496.
Changes in time complexity
n
: number of polygons visited until now (navigation_polys
)m
: number of polygons marked for later visiting (traversable_polys
)In every scenario,
m
increases at a much slower rate thann
.O(n)
toO(log2(m))
(orO(1)
if the polygon has already been visited and no update is needed)O(m)
toO(log2(m))
These changes should result in a big performance improvement on big maps.
Test project
Navigation path finding tests.zip
Benchmark numbers
Below are execution times for
NavigationServer*D.map_get_path
before and after this PR on different map sizes.As you can see, the bigger the map, the bigger the speed-up.
scons platform=windows
(no debug info)Further improvements
There is room for further improvement here.
O(n)
operation. We will invariably loop over every polygon each request. We could use a specialized data structure to improve performance here.I intend to work on these if there is no problem with this PR.