-
Notifications
You must be signed in to change notification settings - Fork 180
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
Going to open a door with the full party make it drop fps considerably #1692
Comments
Probably just the general performance problem / trade-off, unless you can demonstrate this worked better in 0.8.8 or some later version. We'll probably need to add new threads to speed the search (eg. the direction loop in FindPath looks parallelizable), but that wouldn't help on all hardware. And since pathing is critical, we can't just wait until it's done, doing other stuff like processing mouse movement in the meanwhile. |
@lynxlynxlynx I tried on all the tags beginning on the v0.8.8 and in all of them happen the same. Depending where you are the impact is more notable |
the profiler shows we are spending quite a bit of time in |
I dont expect it to amount to much on a release build, but possibly debug builds can benefit we were spending a lot of time inside NormalizeDeltas and we dont need to call it every time #1692
profiling shows we can chew though a lot of time in this function when pathing is thrashing try to improve things by: 1. avoid type narrowing/promotions (use fabs over abs, make signs a double) 2. use std::copysign, on most systems this will be an inline compiler intrinsic implemented with hardware instructions instead of branches it doesnt support the 0 case, but we dont need it since we would be multiplying 0 * 0 in that case anyway which is the same as 0 * 1 or 0 * -1 3. precompute the square of STEP_RADIUS 4. save the squares of dx and dy to reuse #1692
Things still hitch, but those optimizations gave me ~10% improvement (hitches are 10% shorter). We could squeeze another ~14% if we could eliminate ConvertCoordToTile from the pathfinding by having a flavor of Any better fix is going to have to actually change some logic (or offloading to another thread as mentioned) |
I'm not sure it is related, but this looks like a bug to me: Lines 2575 to 2594 in ab71947
the Lines 394 to 397 in ab71947
Am I missing something? |
Which multiplies? Anyway, either we have an issue open (or it was just chat with kmfrick) about subclassing a BasePoint, so we can have Point always be a NavMapPoint and then a separate class be the TileMapPoint to be able to canonically avoid double conversions etc. |
the
Yeah, distinct types would be nice to avoid bugs and for clarity |
I don't see a problem there, it's iterating over the vertices of what would be the tilemap, but still in normal space. |
Ah, so the multiples are converting |
profiling shows significant time spent converting coordinated #1692
eliminates some coordinate conversion make a TODO for how we could further optimize away coordinate conversions #1692
ok, things seem much better to me. We can go a bit further without changing the algorithm in a couple of areas too. |
Is a lot better for me, the only place is when is a narrow place that drops to <3fps. |
It looks like our "bumping" implementation forces the bumped actor to recalculate a path. I imagine this happens quite a bit in narrow corridors. I may be being naïve, but it seems like we could instead find the bumped position, then calculate a path from that position to the current position in the path and then prepend that path segment, which would be much better than completely recalculating a path. |
Hard to say how much that would help or if it'd look good, as in tight spaces the new segment might cause bumping again or repathing. |
Repeated bumping and complete repathing is what appears to be happening currently. The difference is calculating a few nodes of a a new path and prepending it instead of completely recalculating the entire path as is happening now. The problem is exacerbated greatly if the whole party is pathing though a corridor with the destination being far away. I dont know anything about how bumping is implemented, but I would hope it is at least deterministic. It's probably too much to hope that it is physics approximate such that collisions between actors behave like like products of force vectors tho :) |
use our PlotCircle function instead of brute force with wasted iterations and 4 extra Point calculations (this might help out with #1692) The originals probably used an approximation (probably also Bresenham's) so maybe we are now truer to the originals, changing comment about the difference into a TODO to recheck we can also eliminate a redundant bounds check because QuerySearchMap already does this
use our PlotCircle function instead of brute force with wasted iterations and 4 extra Point calculations (this might help out with #1692) The originals probably used an approximation (probably also Bresenham's) so maybe we are now truer to the originals, changing comment about the difference into a TODO to recheck we can also eliminate a redundant bounds check because QuerySearchMap already does this
use our PlotCircle function instead of brute force with wasted iterations and 4 extra Point calculations (this might help out with #1692) The originals probably used an approximation (probably also Bresenham's) so maybe we are now truer to the originals, changing comment about the difference into a TODO to recheck we can also eliminate a redundant bounds check because QuerySearchMap already does this
use our PlotCircle function instead of brute force with wasted iterations and 4 extra Point calculations (this might help out with #1692) The originals probably used an approximation (probably also Bresenham's) so maybe we are now truer to the originals, changing comment about the difference into a TODO to recheck we can also eliminate a redundant bounds check because QuerySearchMap already does this
use our PlotCircle function instead of brute force with wasted iterations and 4 extra Point calculations (this might help out with #1692) The originals probably used an approximation (probably also Bresenham's) so maybe we are now truer to the originals, changing comment about the difference into a TODO to recheck we can also eliminate a redundant bounds check because QuerySearchMap already does this
use our PlotCircle function instead of brute force with wasted iterations and 4 extra Point calculations (this might help out with #1692) The originals probably used an approximation (probably also Bresenham's) so maybe we are now truer to the originals, changing comment about the difference into a TODO to recheck we can also eliminate a redundant bounds check because QuerySearchMap already does this
This should reduce the time wasted in gemrb#1692 a little. This makes the compilers take a way faster sqrt implementation than the precise default, that has accounted for some time lost there. Yet, the issues needs some more attention and remains open as of now.
This should reduce the time wasted in gemrb#1692 a little. This makes the compilers take a way faster sqrt implementation than the precise default, that has accounted for some time lost there. Yet, the issues needs some more attention and remains open as of now.
Yes, the more gemrb/gemrb/core/PathFinder.cpp Lines 374 to 375 in 71bb2f8
Hm, maybe we can exempt party members from this check? Especially when they gathered in front of a door already that isn't blocked by anyone else (Rylock comes to my mind, although I haven't checked whether that's the mechanism here), is there any obvious reason for discard this iteration over this bumping check? |
Wouldn't exempting pcs just drop them on the next check? If that was not a problem it could easily lead to them walking through each other. |
That's just the path planning here, the actual can-bump-on-step test is in Also, as I read the next check, it means it's blocked unless it's passable, travellable (performable) or an actor (potentially bumpable). |
Try it then. 🤷🏾 |
The bad news: When exhausting on a big map, the algorithm is simply expensive, all the observed frame drops are a result of unfortunate geometry/searchmap blocking. It is especially bad when the ignore-actors flag fails the second time with a full group, because there is actually just no path, see BG2 slums: Yet there is a way (I can submit a PR if interested) to reuse a little bit of information to halve the penalty by skipping the ignore-actors run if there wasn't any actor to potentially bump into. The T* stuff doesn't hurt r/n on small maps but on larger ones, we get what we see if there is no path to find. Not sure what to do about this at the moment. |
It's the worst case scenario, so not as bad as it may seem, but optimizations are always welcome. I'm sceptical we could find a faster overall algorithm that would still satisfy all our needs. T* is already an optimization over the A*-like pathfinder we had before, which didn't even support all orientations, let alone bumping. |
The algorithm is fine. I'm thinking about some pre-processing, like: Test whether and what party members are close together (by radius) and whether they have a passable, straight line of sight to each other. Then just pick one PC to do the expensive algorithm, and copy the result (if any) by extending one path element for the rest towards that selected PC's position. This can maybe reduce the calculcation for all these edge-cases even more. |
I've been playing around with other approaches of path finding without calculating so much. One of the attempts looks like this:
This has greatly reduced all these expensive edge cases and frame drops with a mix of reusing path data and relying on a bit of heuristics. So far, the only ugly thing preventing this from testing and judging is that PCs spend a little too much time finding their final spot in the formation. If I come with some idea, I'll be opening a PR. |
I feel like we are possibly putting the cart before the horse. There are a ton of considerations to make when changing path finding. I think we need to figure out exactly what is happening to know the best path forward (pun possibly intended). It seems like the main issue is that we completely recalculate paths at times when we could simply recalculate a portion. Is this not the case? I haven't thoroughly studied the code, but I don't recall seeing any attempts to modify existing paths. Lynx also hinted that there are possibly issues when reaching the end of a path. I think there are big improvements that could be made without having to do anything special. |
I see these main issues:
I'm fully open to ideas. It's just that grouping people by some cheap principles generally turns out to be bearable idea, not perfect in this way of course, and it does not touch the T* code, just a bit of Recalculation of portions of a path sounds good, I just don't have any idea r/n how this is supposed to work like. |
Maybe fixing #1785 would make a difference. |
This problem is even more extreme when playing on higher FPS. I propose another idea: We apply some kind of flood algorithm in a way that two legally adjacent, non-blocking search map cells will be assigned the same number, as their neighbour, starting from top-left. If there is no such neighbour, they will be assigned a different number, so you end up with some kind of map of islands. This map is updated whenever there is a area load, or something mildly permanent changes (like a door). This is linear to the number of search map cells, executed rarely. So if start end destination are on different search map islands, there is no need to initiate path-finding (save 6 times for a full party). |
That wouldn't change anything for door approaches though. But it appears this issue is now hosting several issues and should be split into individual reports / discussions. |
Is it? Aside from the link to #1785, the underlying problem are cases that exhaust the algorithm with a full party on big maps, isn't it? Regardless why. Sure, this won't fix the doors or blocking actors but do we see some generic solution? |
The title and first post are about "same island" problems, while the stuff about the sphere is not. With all the work that has already been done, the first part may be just a duplicate of #1785 now. Worst case scenarios like the separate slums area will require a different approach. |
Then, on the other hand, we could use this to distinguish the problems. One case: skipping pathfinding completely, or otherweise trying something with actor bumping, moving, ordering instead, since we know it's a same-island problem. |
It's just unfortunate that github doesn't allow splitting issues, you can only do one comment and then manually edit in all the rest. |
Hello,
The [GameScript/ERROR]: Invalid scripting action: 'runtopoint([1052.1059])' is new, didn't happen before, and I now I can't get out of places without a lot of work. |
That's a pst-only action, other games don't support running. Harmless error, you just doubleclicked. |
Opened a separate #2079 and closing this — the OP bug is fixed. |
Bug description
On the bridge district (Where I notice) trying to open a door brings down the fps. It's only when the full party is selected.
I believe this is related to #1441
Steps to reproduce
Expected behavior
It not should drop the fps like that
Screenshots
frame-drops.mp4
GemRB version (check as many as you know apply)
Video Driver (check as many as you know apply)
USE_OPENGL_BACKEND
USE_OPENGL_BACKEND
The text was updated successfully, but these errors were encountered: