perf: save more metadata per "list of terrains" for fast lookups, this time for edge tiles

This commit is contained in:
yairm210 2024-12-15 19:53:01 +02:00
parent 7bc5047ace
commit 1a0bb512bf
3 changed files with 17 additions and 7 deletions

View File

@ -75,8 +75,17 @@ class TileMap(initialCapacity: Int = 10) : IsPartOfGameInfoSerialization {
@Transient @Transient
var ruleset: Ruleset? = null var ruleset: Ruleset? = null
data class TerrainListData(
val uniques: UniqueMap,
val terrainNameSet: Set<String>
){
companion object{
val EMPTY = TerrainListData(UniqueMap.EMPTY, emptySet())
}
}
@Transient @Transient
var tileUniqueMapCache = ConcurrentHashMap<List<String>, UniqueMap>() var tileUniqueMapCache = ConcurrentHashMap<List<String>, TerrainListData>()
@Transient @Transient
var tileMatrix = ArrayList<ArrayList<Tile?>>() // this works several times faster than a hashmap, the performance difference is really astounding var tileMatrix = ArrayList<ArrayList<Tile?>>() // this works several times faster than a hashmap, the performance difference is really astounding

View File

@ -156,7 +156,7 @@ class Tile : IsPartOfGameInfoSerialization, Json.Serializable {
private set private set
@Transient @Transient
var terrainUniqueMap = UniqueMap.EMPTY var cachedTerrainData = TileMap.TerrainListData.EMPTY
private set private set
@Transient @Transient
@ -373,10 +373,10 @@ class Tile : IsPartOfGameInfoSerialization, Json.Serializable {
internal var stateThisTile: StateForConditionals = StateForConditionals.EmptyState internal var stateThisTile: StateForConditionals = StateForConditionals.EmptyState
/** Checks whether any of the TERRAINS of this tile has a certain unique */ /** Checks whether any of the TERRAINS of this tile has a certain unique */
fun terrainHasUnique(uniqueType: UniqueType, state: StateForConditionals = stateThisTile) = fun terrainHasUnique(uniqueType: UniqueType, state: StateForConditionals = stateThisTile) =
terrainUniqueMap.getMatchingUniques(uniqueType, state).any() cachedTerrainData.uniques.hasMatchingUnique(uniqueType, state)
/** Get all uniques of this type that any TERRAIN on this tile has */ /** Get all uniques of this type that any TERRAIN on this tile has */
fun getTerrainMatchingUniques(uniqueType: UniqueType, stateForConditionals: StateForConditionals = stateThisTile ): Sequence<Unique> { fun getTerrainMatchingUniques(uniqueType: UniqueType, stateForConditionals: StateForConditionals = stateThisTile ): Sequence<Unique> {
return terrainUniqueMap.getMatchingUniques(uniqueType, stateForConditionals) return cachedTerrainData.uniques.getMatchingUniques(uniqueType, stateForConditionals)
} }
/** Get all uniques of this type that any part of this tile has: terrains, improvement, resource */ /** Get all uniques of this type that any part of this tile has: terrains, improvement, resource */
@ -835,8 +835,9 @@ class Tile : IsPartOfGameInfoSerialization, Json.Serializable {
val terrainNameList = allTerrains.map { it.name }.toList() val terrainNameList = allTerrains.map { it.name }.toList()
// List hash is function of all its items, so the same items in the same order will always give the same hash // List hash is function of all its items, so the same items in the same order will always give the same hash
terrainUniqueMap = tileMap.tileUniqueMapCache.getOrPut(terrainNameList) { cachedTerrainData = tileMap.tileUniqueMapCache.getOrPut(terrainNameList) {
UniqueMap(allTerrains.flatMap { it.uniqueObjects }) TileMap.TerrainListData(UniqueMap(allTerrains.flatMap { it.uniqueObjects }),
terrainNameList.toSet())
} }
} }

View File

@ -109,7 +109,7 @@ class TileLayerTerrain(tileGroup: TileGroup, size: Float) : TileLayer(tileGroup,
// Required for performance - full matchesFilter is too expensive for something that needs to run every update() // Required for performance - full matchesFilter is too expensive for something that needs to run every update()
fun matchesFilterMinimal(originTile: Tile, filter: String): Boolean { fun matchesFilterMinimal(originTile: Tile, filter: String): Boolean {
if (originTile.allTerrains.any { it.name == filter }) return true if (originTile.cachedTerrainData.terrainNameSet.contains(filter)) return true
if (originTile.getBaseTerrain().type.name == filter) return true if (originTile.getBaseTerrain().type.name == filter) return true
return false return false
} }