Resolved #9745 - memory improvement, cache uniquemap for tiles with identical terrain

This commit is contained in:
Yair Morgenstern 2023-07-09 10:12:16 +03:00
parent d9b1d22949
commit 31f6a406c2
2 changed files with 21 additions and 4 deletions

View File

@ -12,8 +12,10 @@ import com.unciv.models.metadata.Player
import com.unciv.models.ruleset.Ruleset
import com.unciv.models.ruleset.nation.Nation
import com.unciv.models.ruleset.tile.TerrainType
import com.unciv.models.ruleset.unique.UniqueMap
import com.unciv.models.ruleset.unique.UniqueType
import java.lang.Integer.max
import java.util.concurrent.ConcurrentHashMap
import kotlin.math.abs
/** An Unciv map with all properties as produced by the [map editor][com.unciv.ui.screens.mapeditorscreen.MapEditorScreen]
@ -60,6 +62,9 @@ class TileMap(initialCapacity: Int = 10) : IsPartOfGameInfoSerialization {
@Transient
var ruleset: Ruleset? = null
@Transient
var tileUniqueMapCache = ConcurrentHashMap<String, UniqueMap>()
@Transient
var tileMatrix = ArrayList<ArrayList<Tile?>>() // this works several times faster than a hashmap, the performance difference is really astounding
@ -140,6 +145,7 @@ class TileMap(initialCapacity: Int = 10) : IsPartOfGameInfoSerialization {
toReturn.startingLocations.clear()
toReturn.startingLocations.ensureCapacity(startingLocations.size)
toReturn.startingLocations.addAll(startingLocations)
toReturn.tileUniqueMapCache = tileUniqueMapCache
return toReturn
}

View File

@ -832,9 +832,7 @@ open class Tile : IsPartOfGameInfoSerialization {
yieldAll(terrainFeatureObjects)
}.toList().asSequence() //Save in memory, and return as sequence
val newUniqueMap = UniqueMap()
for (terrain in allTerrains)
newUniqueMap.addUniques(terrain.uniqueObjects)
updateUniqueMap()
lastTerrain = when {
terrainFeatures.isNotEmpty() -> ruleset.terrains[terrainFeatures.last()]
@ -842,7 +840,20 @@ open class Tile : IsPartOfGameInfoSerialization {
naturalWonder != null -> getNaturalWonder()
else -> getBaseTerrain()
}
terrainUniqueMap = newUniqueMap
}
private fun updateUniqueMap() {
if (!::tileMap.isInitialized) return // This tile is a fake tile, for visual display only (e.g. map editor, civilopedia)
val terrainString = allTerrains.joinToString(";") { it.name }
val cachedUniqueMap = tileMap.tileUniqueMapCache[terrainString]
terrainUniqueMap = if (cachedUniqueMap != null) cachedUniqueMap
else {
val newUniqueMap = UniqueMap()
for (terrain in allTerrains)
newUniqueMap.addUniques(terrain.uniqueObjects)
tileMap.tileUniqueMapCache[terrainString] = newUniqueMap
newUniqueMap
}
}
fun addTerrainFeature(terrainFeature: String) =