Cache serving pipeline fleet to eliminate per-tick rebuilds and reduce GC pressure

Fleet template is now rebuilt only when deploymentVersion changes (~68 times per
28,800-tick run instead of every tick). Reuses module-level Maps, arrays, and
utilization objects instead of allocating new ones each tick. Replaces 4x
Object.values().reduce() with single-pass aggregation and sorts fleet in-place.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-26 19:51:13 -04:00
parent bbb69a315c
commit 57a81be769
7 changed files with 190 additions and 99 deletions
@@ -119,6 +119,7 @@ export function deployModel(state: GameState, modelId: string): boolean {
if (!model) return false;
model.isDeployed = true;
state.models.deploymentVersion = (state.models.deploymentVersion ?? 0) + 1;
for (const pl of state.models.productLines) {
pl.modelId = modelId;
+2 -1
View File
@@ -1,5 +1,5 @@
import type { GameState } from '@ai-tycoon/shared';
import { processTick, setAchievementDefinitions, ACHIEVEMENT_DEFINITIONS, resetResearchBonusCache } from '@ai-tycoon/game-engine';
import { processTick, setAchievementDefinitions, ACHIEVEMENT_DEFINITIONS, resetResearchBonusCache, resetFleetCache } from '@ai-tycoon/game-engine';
import type { TickNotification } from '@ai-tycoon/game-engine';
import type { Strategy, SimulationMetrics } from './strategies/types';
import { collectMetrics } from './analysis/metrics';
@@ -78,6 +78,7 @@ export function runSimulation(config: SimulationConfig): SimulationResult {
resetIds();
resetResearchBonusCache();
resetFleetCache();
let rng: ReturnType<typeof createSeededRNG> | null = null;
if (config.seed !== undefined) {