mirror of
https://github.com/yairm210/Unciv.git
synced 2025-01-03 21:40:31 +07:00
performance: Use the same trick of 'save unfiltered, return filtered' for cached city uniques, so devs don't need to worry about cache state when improving performance!
Big DUH moment, we've been applying this same trick everywhere but haven't generalized it yet... This will both make performance improvements easier, AND improve readability!
This commit is contained in:
parent
97b16d2b5f
commit
f8ccefd10c
@ -27,23 +27,24 @@ class TileStatFunctions(val tile: Tile) {
|
||||
val stateForConditionals = StateForConditionals(civInfo = observingCiv, city = city, tile = tile)
|
||||
|
||||
if (city != null) {
|
||||
var tileUniques =
|
||||
val statsFromTilesUniques =
|
||||
localUniqueCache.forCityGetMatchingUniques(
|
||||
city, UniqueType.StatsFromTiles, true)
|
||||
city, UniqueType.StatsFromTiles,
|
||||
stateForConditionals)
|
||||
.filter { city.matchesFilter(it.params[2]) }
|
||||
tileUniques += localUniqueCache.forCityGetMatchingUniques(
|
||||
city, UniqueType.StatsFromObject, true)
|
||||
for (unique in tileUniques) {
|
||||
if (!unique.conditionalsApply(stateForConditionals)) continue
|
||||
|
||||
val statsFromObjectsUniques = localUniqueCache.forCityGetMatchingUniques(
|
||||
city, UniqueType.StatsFromObject, stateForConditionals)
|
||||
|
||||
for (unique in statsFromTilesUniques + statsFromObjectsUniques) {
|
||||
val tileType = unique.params[1]
|
||||
if (!tile.matchesTerrainFilter(tileType, observingCiv)) continue
|
||||
stats.add(unique.stats)
|
||||
}
|
||||
|
||||
for (unique in localUniqueCache.forCityGetMatchingUniques(
|
||||
city, UniqueType.StatsFromTilesWithout, true)) {
|
||||
city, UniqueType.StatsFromTilesWithout, stateForConditionals)) {
|
||||
if (
|
||||
unique.conditionalsApply(stateForConditionals) &&
|
||||
tile.matchesTerrainFilter(unique.params[1]) &&
|
||||
!tile.matchesTerrainFilter(unique.params[2]) &&
|
||||
city.matchesFilter(unique.params[3])
|
||||
@ -116,21 +117,18 @@ class TileStatFunctions(val tile: Tile) {
|
||||
val stateForConditionals = StateForConditionals(civInfo = observingCiv, city = city, 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, true)
|
||||
city, UniqueType.StatPercentFromObject, stateForConditionals)
|
||||
|
||||
for (unique in cachedStatPercentFromObjectCityUniques) {
|
||||
if (!unique.conditionalsApply(stateForConditionals)) continue
|
||||
val tileFilter = unique.params[2]
|
||||
if (tile.matchesTerrainFilter(tileFilter, observingCiv))
|
||||
stats[Stat.valueOf(unique.params[1])] += unique.params[0].toFloat()
|
||||
}
|
||||
|
||||
val cachedAllStatPercentFromObjectCityUniques = uniqueCache.forCityGetMatchingUniques(
|
||||
city, UniqueType.AllStatsPercentFromObject, true)
|
||||
city, UniqueType.AllStatsPercentFromObject, stateForConditionals)
|
||||
for (unique in cachedAllStatPercentFromObjectCityUniques) {
|
||||
if (!unique.conditionalsApply(stateForConditionals)) continue
|
||||
val tileFilter = unique.params[1]
|
||||
if (!tile.matchesTerrainFilter(tileFilter, observingCiv)) continue
|
||||
val statPercentage = unique.params[0].toFloat()
|
||||
@ -257,13 +255,8 @@ class TileStatFunctions(val tile: Tile) {
|
||||
val stats = Stats()
|
||||
|
||||
fun statsFromTiles(){
|
||||
// Since the conditionalState contains the current tile, it is different for each 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, 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 tileUniques = uniqueCache.forCityGetMatchingUniques(city, UniqueType.StatsFromTiles, conditionalState)
|
||||
.filter { city.matchesFilter(it.params[2]) }
|
||||
val improvementUniques =
|
||||
improvement.getMatchingUniques(UniqueType.ImprovementStatsOnTile, conditionalState)
|
||||
|
||||
@ -278,12 +271,11 @@ class TileStatFunctions(val tile: Tile) {
|
||||
statsFromTiles()
|
||||
|
||||
fun statsFromObject() {
|
||||
// Same as above - cache holds unfiltered uniques for the city, while we use only the filtered ones
|
||||
val uniques = uniqueCache.forCityGetMatchingUniques(
|
||||
city,
|
||||
UniqueType.StatsFromObject,
|
||||
true
|
||||
).filter { it.conditionalsApply(conditionalState) }
|
||||
conditionalState
|
||||
)
|
||||
for (unique in uniques) {
|
||||
if (improvement.matchesFilter(unique.params[1])) {
|
||||
stats.add(unique.stats)
|
||||
@ -305,13 +297,11 @@ class TileStatFunctions(val tile: Tile) {
|
||||
val conditionalState = StateForConditionals(civInfo = observingCiv, city = city, tile = tile)
|
||||
|
||||
if (city != null) {
|
||||
// As above, since the conditional is tile-dependant,
|
||||
// we save uniques in the cache without conditional filtering, and use only filtered ones
|
||||
val allStatPercentUniques = cityUniqueCache.forCityGetMatchingUniques(
|
||||
city,
|
||||
UniqueType.AllStatsPercentFromObject,
|
||||
true
|
||||
).filter { it.conditionalsApply(conditionalState) }
|
||||
conditionalState
|
||||
)
|
||||
for (unique in allStatPercentUniques) {
|
||||
if (!improvement.matchesFilter(unique.params[1])) continue
|
||||
for (stat in Stat.values()) {
|
||||
@ -319,12 +309,11 @@ class TileStatFunctions(val tile: Tile) {
|
||||
}
|
||||
}
|
||||
|
||||
// Same trick different unique - not sure if worth generalizing this 'late apply' of conditions?
|
||||
val statPercentUniques = cityUniqueCache.forCityGetMatchingUniques(
|
||||
city,
|
||||
UniqueType.StatPercentFromObject,
|
||||
true
|
||||
).filter { it.conditionalsApply(conditionalState) }
|
||||
conditionalState
|
||||
)
|
||||
|
||||
for (unique in statPercentUniques) {
|
||||
if (!improvement.matchesFilter(unique.params[2])) continue
|
||||
|
@ -323,21 +323,20 @@ class LocalUniqueCache(val cache:Boolean = true) {
|
||||
fun forCityGetMatchingUniques(
|
||||
city: City,
|
||||
uniqueType: UniqueType,
|
||||
ignoreConditionals: Boolean = false
|
||||
stateForConditionals: StateForConditionals = StateForConditionals(city.civ, city)
|
||||
): Sequence<Unique> {
|
||||
// City uniques are a combination of *global civ* uniques plus *city relevant* uniques (see City.getMatchingUniques())
|
||||
// We can cache the civ uniques separately, so if we have several cities using the same cache,
|
||||
// we can cache the list of *civ uniques* to reuse between cities.
|
||||
// This is assuming that we're ignoring conditionals, because otherwise -
|
||||
// the conditionals will render the the *filtered uniques* different anyway, so there's no reason to cache...
|
||||
val uniques = if (!ignoreConditionals) city.getMatchingUniques(uniqueType, StateForConditionals(city.civ, city))
|
||||
else forCivGetMatchingUniques(city.civ, uniqueType, StateForConditionals.IgnoreConditionals) +
|
||||
val unfilteredUniques = forCivGetMatchingUniques(city.civ, uniqueType, StateForConditionals.IgnoreConditionals) +
|
||||
city.getLocalMatchingUniques(uniqueType, StateForConditionals.IgnoreConditionals)
|
||||
|
||||
return get(
|
||||
"city-${city.id}-${uniqueType.name}-${ignoreConditionals}",
|
||||
uniques
|
||||
)
|
||||
"city-${city.id}-${uniqueType.name}",
|
||||
unfilteredUniques
|
||||
).filter { it.conditionalsApply(stateForConditionals) }
|
||||
}
|
||||
|
||||
fun forCivGetMatchingUniques(
|
||||
|
Loading…
Reference in New Issue
Block a user