From 159ae86960bee171943e964c920e76239be0b358 Mon Sep 17 00:00:00 2001 From: SomeTroglodyte <63000004+SomeTroglodyte@users.noreply.github.com> Date: Tue, 2 May 2023 22:26:39 +0200 Subject: [PATCH] Reduce a few memory allocations (#9312) --- core/src/com/unciv/logic/GameInfo.kt | 12 +++++++---- core/src/com/unciv/logic/map/TileMap.kt | 22 ++++++++++++-------- core/src/com/unciv/models/ruleset/Ruleset.kt | 2 +- 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/core/src/com/unciv/logic/GameInfo.kt b/core/src/com/unciv/logic/GameInfo.kt index 853017a611..ce65a40305 100644 --- a/core/src/com/unciv/logic/GameInfo.kt +++ b/core/src/com/unciv/logic/GameInfo.kt @@ -34,7 +34,9 @@ import com.unciv.ui.audio.MusicMood import com.unciv.ui.audio.MusicTrackChooserFlags import com.unciv.utils.DebugUtils import com.unciv.utils.debug -import java.util.* +import java.util.UUID +import kotlin.collections.ArrayList +import kotlin.collections.HashMap /** @@ -163,9 +165,11 @@ class GameInfo : IsPartOfGameInfoSerialization, HasGameInfoSerializationVersion fun clone(): GameInfo { val toReturn = GameInfo() toReturn.tileMap = tileMap.clone() - toReturn.civilizations.addAll(civilizations.map { it.clone() }) + toReturn.civilizations = civilizations.asSequence() + .map { it.clone() } + .toCollection(ArrayList(civilizations.size)) toReturn.barbarians = barbarians.clone() - toReturn.religions.putAll(religions.map { Pair(it.key, it.value.clone()) }) + toReturn.religions.putAll(religions.asSequence().map { it.key to it.value.clone() }) toReturn.currentPlayer = currentPlayer toReturn.currentTurnStartTime = currentTurnStartTime toReturn.turns = turns @@ -175,7 +179,7 @@ class GameInfo : IsPartOfGameInfoSerialization, HasGameInfoSerializationVersion toReturn.diplomaticVictoryVotesCast.putAll(diplomaticVictoryVotesCast) toReturn.oneMoreTurnMode = oneMoreTurnMode toReturn.customSaveLocation = customSaveLocation - toReturn.victoryData = victoryData + toReturn.victoryData = victoryData?.copy() toReturn.historyStartTurn = historyStartTurn return toReturn diff --git a/core/src/com/unciv/logic/map/TileMap.kt b/core/src/com/unciv/logic/map/TileMap.kt index e0842616b2..773414540c 100644 --- a/core/src/com/unciv/logic/map/TileMap.kt +++ b/core/src/com/unciv/logic/map/TileMap.kt @@ -20,8 +20,10 @@ import kotlin.math.abs * or [MapGenerator][com.unciv.logic.map.mapgenerator.MapGenerator]; or as part of a running [game][GameInfo]. * * Note: Will be Serialized -> Take special care with lateinit and lazy! + * + * @param initialCapacity Passed to constructor of [tileList] */ -class TileMap : IsPartOfGameInfoSerialization { +class TileMap(initialCapacity: Int = 10) : IsPartOfGameInfoSerialization { companion object { /** Legacy way to store starting locations - now this is used only in [translateStartingLocationsFromMap] */ const val startingLocationPrefix = "StartingLocation " @@ -38,7 +40,7 @@ class TileMap : IsPartOfGameInfoSerialization { var mapParameters = MapParameters() - var tileList = ArrayList() + var tileList = ArrayList(initialCapacity) /** Structure geared for simple serialization by Gdx.Json (which is a little blind to kotlin collections, especially HashSet) * @param position [Vector2] of the location @@ -93,11 +95,9 @@ class TileMap : IsPartOfGameInfoSerialization { //endregion //region Constructors - /** for json parsing, we need to have a default constructor */ - constructor() - /** creates a hexagonal map of given radius (filled with grassland) */ - constructor(radius: Int, ruleset: Ruleset, worldWrap: Boolean = false) { + constructor(radius: Int, ruleset: Ruleset, worldWrap: Boolean = false) + : this (HexMath.getNumberOfTilesInHexagon(radius)) { startingLocations.clear() val firstAvailableLandTerrain = MapLandmassGenerator.getInitializationTerrain(ruleset, TerrainType.Land) for (vector in HexMath.getVectorsInDistance(Vector2.Zero, radius, worldWrap)) @@ -106,7 +106,8 @@ class TileMap : IsPartOfGameInfoSerialization { } /** creates a rectangular map of given width and height (filled with grassland) */ - constructor(width: Int, height: Int, ruleset: Ruleset, worldWrap: Boolean = false) { + constructor(width: Int, height: Int, ruleset: Ruleset, worldWrap: Boolean = false) + : this(width * height) { startingLocations.clear() val firstAvailableLandTerrain = MapLandmassGenerator.getInitializationTerrain(ruleset, TerrainType.Land) @@ -130,13 +131,16 @@ class TileMap : IsPartOfGameInfoSerialization { /** @return a deep-copy clone of the serializable fields, no transients initialized */ fun clone(): TileMap { - val toReturn = TileMap() - toReturn.tileList.addAll(tileList.map { it.clone() }) + val toReturn = TileMap(tileList.size) + toReturn.tileList.addAll(tileList.asSequence().map { it.clone() }) toReturn.mapParameters = mapParameters toReturn.ruleset = ruleset + + // Note during normal play this is empty. Supported for MapEditorScreen.getMapCloneForSave. toReturn.startingLocations.clear() toReturn.startingLocations.ensureCapacity(startingLocations.size) toReturn.startingLocations.addAll(startingLocations) + return toReturn } diff --git a/core/src/com/unciv/models/ruleset/Ruleset.kt b/core/src/com/unciv/models/ruleset/Ruleset.kt index 00f84112b9..d38e0d3c28 100644 --- a/core/src/com/unciv/models/ruleset/Ruleset.kt +++ b/core/src/com/unciv/models/ruleset/Ruleset.kt @@ -109,7 +109,7 @@ class Ruleset { } private fun createHashmap(items: Array): LinkedHashMap { - val hashMap = LinkedHashMap() + val hashMap = LinkedHashMap(items.size) for (item in items) hashMap[item.name] = item return hashMap