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

Segregate inter level hostility #44107

Merged

Conversation

kevingranade
Copy link
Member

Summary

SUMMARY: Performance "Reduce inter-faction hostility overhead with a inter-level visibility cache."

Purpose of change

Execution time when passing time when near a large number of monsters hostile to each other is slow, and profiling says it's dominated by inter-faction vision checks.

Describe the solution

One of the dominant use cases where this happens is inside or near a lab complex since there are many monsters hostile to each other separated by walls. This use case is ameniable to special handling by seperating the maps of creatures based on levels, and only checking for visibility between monsters on levels that have some kind of visibility between them.
I added a bool per map level cache entry that tracks whether the level has a contiguous floor. This is calculated essentially for free in build_floor_cache.
An accessor walks these entries and tabulates which levels the origin level has visibility to as a bitset.
I split the monster faction map by level, within the entry for each faction, there is a sparse map of levels, each of which contains a data structure holding the actual weak pointers to the monsters.
When scanning the faction map for enemies, the code can now exit early on entries on levels not visible to the current monster.

Describe alternatives you've considered

This still consumes a significant amount of processing time, though it is no longer dominant, so further optimization is warranted.

Testing

A timing test of waiting outside a lab for three hours tool 52 seconds before this change, and 40.75 seconds after this change. Profiling with perf also indicated that this particular codepath is doing drastically less work. The new cache creation code is not appearing in profiling.

@anothersimulacrum anothersimulacrum added Code: Performance Performance boosting code (CPU, memory, etc.) Monsters Monsters both friendly and unfriendly. NPC / Factions NPCs, AI, Speech, Factions, Ownership labels Sep 11, 2020
@kevingranade kevingranade force-pushed the segregate-inter-level-hostility branch from 0ae6c39 to c95c04f Compare September 11, 2020 06:02
src/map.h Outdated Show resolved Hide resolved
@Aivean
Copy link
Contributor

Aivean commented Sep 12, 2020

An idea for the future, we can use the new no_floor_gaps cache to speed up sunlight_cache further (avoid iterating over the floor if we know there are no gaps).

UPD: after a bit of thinking, that won't actually speed up anything, as the fully_inside -> fully_outside transition doesn't happen directly, unless the current map is completely flat. What can help there is to check submap::is_uniform.

@kevingranade kevingranade force-pushed the segregate-inter-level-hostility branch from f142c03 to d6baa73 Compare September 13, 2020 00:30
@kevingranade kevingranade force-pushed the segregate-inter-level-hostility branch from d6baa73 to 3ec366f Compare September 14, 2020 03:00
@kevingranade
Copy link
Member Author

Updated to opportunistically shortcut out of checking for NPCs and player as well.

src/map.h Outdated Show resolved Hide resolved
}
monster &mon = *shared;
float rating = rate_target( mon, dist, smart_planning );
if( rating == dist ) {
Copy link
Contributor

Choose a reason for hiding this comment

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

It is not safe to compare two floats like that.

@kevingranade
Copy link
Member Author

@alvean we could add the opposite cache value of all_open or similar built the same way and use it to determine the first layer with obstacles more cheaply.

@ZhilkinSerg the only time I expect that code to trigger is when the relative positions of monsters are rotations of each other, i.e. 1,7 vs 7,1, and in that case I do expect them to trigger reliably. I'm not against adding some kind of epsilon here to make it trigger a bit more, but that requires a bit more thought and I don't want to mess with it in this pr.

@Aivean
Copy link
Contributor

Aivean commented Sep 15, 2020

@alvean we could add the opposite cache value of all_open or similar built the same way and use it to determine the first layer with obstacles more cheaply.

Good idea, however I'm going to try checking submap::is_uniform first, it might work well enough.

@ZhilkinSerg ZhilkinSerg merged commit 65a8b8a into CleverRaven:master Sep 16, 2020
@kevingranade kevingranade deleted the segregate-inter-level-hostility branch September 18, 2020 05:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Code: Performance Performance boosting code (CPU, memory, etc.) Monsters Monsters both friendly and unfriendly. NPC / Factions NPCs, AI, Speech, Factions, Ownership
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants