From 259eeeb56cf31ddfb3497c230351a80330cc341a Mon Sep 17 00:00:00 2001 From: Yair Morgenstern Date: Sat, 17 Jun 2023 23:47:49 +0300 Subject: [PATCH] Performance improvements - improvementFilter checks map instead of array for textual match - forCityGetMatchingUniques does not string-serialize conditionals - revealed by flame chart to be significant --- .../unciv/logic/map/tile/TileStatFunctions.kt | 18 +++++++++--------- .../models/ruleset/tile/TileImprovement.kt | 2 +- .../com/unciv/models/ruleset/unique/Unique.kt | 7 +++---- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/core/src/com/unciv/logic/map/tile/TileStatFunctions.kt b/core/src/com/unciv/logic/map/tile/TileStatFunctions.kt index 215fbf4669..48fa278509 100644 --- a/core/src/com/unciv/logic/map/tile/TileStatFunctions.kt +++ b/core/src/com/unciv/logic/map/tile/TileStatFunctions.kt @@ -29,10 +29,10 @@ class TileStatFunctions(val tile: Tile) { if (city != null) { var tileUniques = localUniqueCache.forCityGetMatchingUniques( - city, UniqueType.StatsFromTiles, StateForConditionals.IgnoreConditionals) + city, UniqueType.StatsFromTiles, true) .filter { city.matchesFilter(it.params[2]) } tileUniques += localUniqueCache.forCityGetMatchingUniques( - city, UniqueType.StatsFromObject, StateForConditionals.IgnoreConditionals) + city, UniqueType.StatsFromObject, true) for (unique in tileUniques) { if (!unique.conditionalsApply(stateForConditionals)) continue val tileType = unique.params[1] @@ -41,7 +41,7 @@ class TileStatFunctions(val tile: Tile) { } for (unique in localUniqueCache.forCityGetMatchingUniques( - city, UniqueType.StatsFromTilesWithout, StateForConditionals.IgnoreConditionals)) { + city, UniqueType.StatsFromTilesWithout, true)) { if ( unique.conditionalsApply(stateForConditionals) && tile.matchesTerrainFilter(unique.params[1]) && @@ -118,7 +118,7 @@ class TileStatFunctions(val tile: Tile) { if (city != null) { // Since the tile changes every time, we cache all uniques, and filter by conditional state only when iterating val cachedStatPercentFromObjectCityUniques = uniqueCache.forCityGetMatchingUniques( - city, UniqueType.StatPercentFromObject, StateForConditionals.IgnoreConditionals) + city, UniqueType.StatPercentFromObject, true) for (unique in cachedStatPercentFromObjectCityUniques) { if (!unique.conditionalsApply(stateForConditionals)) continue @@ -128,7 +128,7 @@ class TileStatFunctions(val tile: Tile) { } val cachedAllStatPercentFromObjectCityUniques = uniqueCache.forCityGetMatchingUniques( - city, UniqueType.AllStatsPercentFromObject, StateForConditionals.IgnoreConditionals) + city, UniqueType.AllStatsPercentFromObject, true) for (unique in cachedAllStatPercentFromObjectCityUniques) { if (!unique.conditionalsApply(stateForConditionals)) continue val tileFilter = unique.params[1] @@ -243,7 +243,7 @@ class TileStatFunctions(val tile: Tile) { // therefore if we want the cache to be useful it needs to hold the pre-filtered uniques, // and then for each improvement we'll filter the uniques locally. // This is still a MASSIVE save of RAM! - val tileUniques = uniqueCache.forCityGetMatchingUniques(city, UniqueType.StatsFromTiles, StateForConditionals.IgnoreConditionals) + val tileUniques = uniqueCache.forCityGetMatchingUniques(city, UniqueType.StatsFromTiles, true) .filter { city.matchesFilter(it.params[2]) } // These are the uniques for all improvements for this city, .filter { it.conditionalsApply(conditionalState) } // ...and this is those with applicable conditions val improvementUniques = @@ -264,7 +264,7 @@ class TileStatFunctions(val tile: Tile) { val uniques = uniqueCache.forCityGetMatchingUniques( city, UniqueType.StatsFromObject, - StateForConditionals.IgnoreConditionals + true ).filter { it.conditionalsApply(conditionalState) } for (unique in uniques) { if (improvement.matchesFilter(unique.params[1])) { @@ -296,7 +296,7 @@ class TileStatFunctions(val tile: Tile) { val allStatPercentUniques = cityUniqueCache.forCityGetMatchingUniques( city, UniqueType.AllStatsPercentFromObject, - StateForConditionals.IgnoreConditionals + true ).filter { it.conditionalsApply(conditionalState) } for (unique in allStatPercentUniques) { if (!improvement.matchesFilter(unique.params[1])) continue @@ -309,7 +309,7 @@ class TileStatFunctions(val tile: Tile) { val statPercentUniques = cityUniqueCache.forCityGetMatchingUniques( city, UniqueType.StatPercentFromObject, - StateForConditionals.IgnoreConditionals + true ).filter { it.conditionalsApply(conditionalState) } for (unique in statPercentUniques) { diff --git a/core/src/com/unciv/models/ruleset/tile/TileImprovement.kt b/core/src/com/unciv/models/ruleset/tile/TileImprovement.kt index 3f5699952b..075ab6abe8 100644 --- a/core/src/com/unciv/models/ruleset/tile/TileImprovement.kt +++ b/core/src/com/unciv/models/ruleset/tile/TileImprovement.kt @@ -126,7 +126,7 @@ class TileImprovement : RulesetStatsObject() { "All" -> true "All Road" -> isRoad() "Great Improvement", "Great" -> isGreatImprovement() - in uniques -> true + in uniqueMap -> true else -> false } } diff --git a/core/src/com/unciv/models/ruleset/unique/Unique.kt b/core/src/com/unciv/models/ruleset/unique/Unique.kt index 7a583b57b8..a18fb40159 100644 --- a/core/src/com/unciv/models/ruleset/unique/Unique.kt +++ b/core/src/com/unciv/models/ruleset/unique/Unique.kt @@ -311,11 +311,10 @@ class LocalUniqueCache(val cache:Boolean = true) { fun forCityGetMatchingUniques( city: City, uniqueType: UniqueType, - stateForConditionals: StateForConditionals = StateForConditionals( - city.civ, - city - ) + ignoreConditionals: Boolean = false ): Sequence { + val stateForConditionals = if (ignoreConditionals) StateForConditionals.IgnoreConditionals + else StateForConditionals(city.civ, city) return get( "city-${city.id}-${uniqueType.name}-${stateForConditionals}", city.getMatchingUniques(uniqueType, stateForConditionals)