From 1a0bb512bfd939d156ba0be82ac5e22f6da0f502 Mon Sep 17 00:00:00 2001 From: yairm210 Date: Sun, 15 Dec 2024 19:53:01 +0200 Subject: [PATCH] perf: save more metadata per "list of terrains" for fast lookups, this time for edge tiles --- core/src/com/unciv/logic/map/TileMap.kt | 11 ++++++++++- core/src/com/unciv/logic/map/tile/Tile.kt | 11 ++++++----- .../components/tilegroups/layers/TileLayerTerrain.kt | 2 +- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/core/src/com/unciv/logic/map/TileMap.kt b/core/src/com/unciv/logic/map/TileMap.kt index 05fac00eac..84b9389e0e 100644 --- a/core/src/com/unciv/logic/map/TileMap.kt +++ b/core/src/com/unciv/logic/map/TileMap.kt @@ -75,8 +75,17 @@ class TileMap(initialCapacity: Int = 10) : IsPartOfGameInfoSerialization { @Transient var ruleset: Ruleset? = null + data class TerrainListData( + val uniques: UniqueMap, + val terrainNameSet: Set + ){ + companion object{ + val EMPTY = TerrainListData(UniqueMap.EMPTY, emptySet()) + } + } + @Transient - var tileUniqueMapCache = ConcurrentHashMap, UniqueMap>() + var tileUniqueMapCache = ConcurrentHashMap, TerrainListData>() @Transient var tileMatrix = ArrayList>() // this works several times faster than a hashmap, the performance difference is really astounding diff --git a/core/src/com/unciv/logic/map/tile/Tile.kt b/core/src/com/unciv/logic/map/tile/Tile.kt index c5a717c75a..0240a4affd 100644 --- a/core/src/com/unciv/logic/map/tile/Tile.kt +++ b/core/src/com/unciv/logic/map/tile/Tile.kt @@ -156,7 +156,7 @@ class Tile : IsPartOfGameInfoSerialization, Json.Serializable { private set @Transient - var terrainUniqueMap = UniqueMap.EMPTY + var cachedTerrainData = TileMap.TerrainListData.EMPTY private set @Transient @@ -373,10 +373,10 @@ class Tile : IsPartOfGameInfoSerialization, Json.Serializable { internal var stateThisTile: StateForConditionals = StateForConditionals.EmptyState /** Checks whether any of the TERRAINS of this tile has a certain unique */ 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 */ fun getTerrainMatchingUniques(uniqueType: UniqueType, stateForConditionals: StateForConditionals = stateThisTile ): Sequence { - 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 */ @@ -835,8 +835,9 @@ class Tile : IsPartOfGameInfoSerialization, Json.Serializable { 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 - terrainUniqueMap = tileMap.tileUniqueMapCache.getOrPut(terrainNameList) { - UniqueMap(allTerrains.flatMap { it.uniqueObjects }) + cachedTerrainData = tileMap.tileUniqueMapCache.getOrPut(terrainNameList) { + TileMap.TerrainListData(UniqueMap(allTerrains.flatMap { it.uniqueObjects }), + terrainNameList.toSet()) } } diff --git a/core/src/com/unciv/ui/components/tilegroups/layers/TileLayerTerrain.kt b/core/src/com/unciv/ui/components/tilegroups/layers/TileLayerTerrain.kt index eb63c03d58..2c62c6ebbe 100644 --- a/core/src/com/unciv/ui/components/tilegroups/layers/TileLayerTerrain.kt +++ b/core/src/com/unciv/ui/components/tilegroups/layers/TileLayerTerrain.kt @@ -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() 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 return false }