mirror of
https://github.com/nolen777/eagle0.git
synced 2026-07-29 00:55:43 +00:00
Only load outstanding shardok battles on game load
Previously, we loaded ALL .e0s shardok battle files when loading a game, even though most battles are completed. For a game with 71 battles, this was loading ~70 unnecessary files. Now we: 1. Load the e0a file first and reconstruct the GameState 2. Extract the outstanding battle IDs from outstandingBattles 3. Only load .e0s files for battles that are still in progress 4. Use parallel loading (via Futures) if > 4 files need loading This should significantly reduce game load time for games with many completed battles. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -160,18 +160,9 @@ object PersistedHistory {
|
||||
.sortBy(_.dropRight(persistence.eagleExtension.length).toInt)
|
||||
.lastOption
|
||||
|
||||
val shardokKeys = allKeys.filter(_.endsWith(persistence.shardokExtension))
|
||||
val shardokStartTime = System.currentTimeMillis()
|
||||
val shardokGames =
|
||||
shardokKeys
|
||||
.map(persister.retrieveAsStream)
|
||||
.flatMap(_.toOption)
|
||||
.flatMap(inputStream =>
|
||||
ProtoParser
|
||||
.parseZipped[ShardokResults](inputStream)(using ShardokResults)
|
||||
)
|
||||
val shardokDuration = System.currentTimeMillis() - shardokStartTime
|
||||
val allShardokKeys = allKeys.filter(_.endsWith(persistence.shardokExtension))
|
||||
|
||||
// Load e0a file first to determine which shardok battles are outstanding
|
||||
val e0aStartTime = System.currentTimeMillis()
|
||||
val e0aResult = lastKey
|
||||
.map(persister.retrieveAsStream)
|
||||
@@ -201,6 +192,31 @@ object PersistedHistory {
|
||||
chunkHistory ++ recoveredHistory
|
||||
} else chunkHistory
|
||||
|
||||
val e0aDuration = System.currentTimeMillis() - e0aStartTime
|
||||
|
||||
// Get the final game state to determine outstanding battles
|
||||
val finalState = recentHistory.lastOption
|
||||
.map(_.scalaGameState)
|
||||
.getOrElse(GameStateConverter.fromProto(pg.startingState.get))
|
||||
|
||||
// Only load shardok files for outstanding battles
|
||||
val outstandingBattleIds = finalState.outstandingBattles.map(_.shardokGameId).toSet
|
||||
val neededShardokKeys = allShardokKeys.filter { key =>
|
||||
val shardokId = key.dropRight(persistence.shardokExtension.length)
|
||||
outstandingBattleIds.contains(shardokId)
|
||||
}
|
||||
|
||||
val shardokStartTime = System.currentTimeMillis()
|
||||
val shardokGames = loadShardokFiles(persister, neededShardokKeys)
|
||||
val shardokDuration = System.currentTimeMillis() - shardokStartTime
|
||||
|
||||
println(
|
||||
s"[GameLoad] gameId=0x${gameId.toHexString}: " +
|
||||
s"e0a files=${e0aKeys.size} (loaded last 1 in ${e0aDuration}ms), " +
|
||||
s"e0s files=${neededShardokKeys.size}/${allShardokKeys.size} outstanding loaded in ${shardokDuration}ms, " +
|
||||
s"total=${e0aDuration + shardokDuration}ms"
|
||||
)
|
||||
|
||||
PersistedHistory(
|
||||
startingState = pg.startingState.get,
|
||||
directory = directory,
|
||||
@@ -210,18 +226,35 @@ object PersistedHistory {
|
||||
persister = persister
|
||||
)
|
||||
}
|
||||
val e0aDuration = System.currentTimeMillis() - e0aStartTime
|
||||
|
||||
println(
|
||||
s"[GameLoad] gameId=0x${gameId.toHexString}: " +
|
||||
s"e0a files=${e0aKeys.size} (loaded last 1 in ${e0aDuration}ms), " +
|
||||
s"e0s files=${shardokKeys.size} loaded in ${shardokDuration}ms, " +
|
||||
s"total=${e0aDuration + shardokDuration}ms"
|
||||
)
|
||||
|
||||
e0aResult
|
||||
}
|
||||
|
||||
private def loadShardokFiles(
|
||||
persister: Persister,
|
||||
keys: Vector[String]
|
||||
): Vector[ShardokResults] = {
|
||||
import scala.concurrent.{Await, Future}
|
||||
import scala.concurrent.ExecutionContext.Implicits.global
|
||||
import scala.concurrent.duration.*
|
||||
|
||||
def loadOne(key: String): Option[ShardokResults] =
|
||||
persister
|
||||
.retrieveAsStream(key)
|
||||
.toOption
|
||||
.flatMap(inputStream => ProtoParser.parseZipped[ShardokResults](inputStream)(using ShardokResults))
|
||||
|
||||
if keys.size > 4 then {
|
||||
// Load in parallel for many files
|
||||
val futures = keys.map(key => Future(loadOne(key)))
|
||||
Await
|
||||
.result(Future.sequence(futures), 30.seconds)
|
||||
.flatten
|
||||
} else {
|
||||
keys.flatMap(loadOne)
|
||||
}
|
||||
}
|
||||
|
||||
def save(
|
||||
persister: Persister,
|
||||
startingIndex: Int,
|
||||
|
||||
Reference in New Issue
Block a user