From 0d84804d81558744f1e657ad30ba6f62b370f9cb Mon Sep 17 00:00:00 2001 From: RoosterDragon Date: Fri, 5 Jul 2024 18:58:36 +0100 Subject: [PATCH] Reduce lag spikes from SquadManagerBotModule. Updating squads is the most expensive part of SquadManagerBotModule. It involves ticking the current squad state. This usually involves finding nearby enemies and evaluating the fuzzy state machine to decide whether to interact with those enemies. Since all the AI squads for a player get ordered on the same tick, this can result in a lag spike. To reduce the impact, we'll spread out the updates over multiple ticks. This means overall all the AI squads will still be refreshed every interval, but it'll be a rolling update rather than all at once. By spreading out the updates we avoid a lag spike from the cumulative updates of all the squads. Now the lag spike is reduced to the worst any single squad update can incur. --- .../Traits/BotModules/SquadManagerBotModule.cs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/OpenRA.Mods.Common/Traits/BotModules/SquadManagerBotModule.cs b/OpenRA.Mods.Common/Traits/BotModules/SquadManagerBotModule.cs index 8e730db8c6..939288eb9a 100644 --- a/OpenRA.Mods.Common/Traits/BotModules/SquadManagerBotModule.cs +++ b/OpenRA.Mods.Common/Traits/BotModules/SquadManagerBotModule.cs @@ -125,6 +125,7 @@ namespace OpenRA.Mods.Common.Traits readonly HashSet activeUnits = new(); public List Squads = new(); + readonly Stack squadsPendingUpdate = new(); readonly ActorIndex.NamesAndTrait constructionYardBuildings; IBot bot; @@ -347,7 +348,16 @@ namespace OpenRA.Mods.Common.Traits { attackForceTicks = Info.AttackForceInterval; foreach (var s in Squads) - s.Update(); + squadsPendingUpdate.Push(s); + } + + // PERF: Spread out squad updates across multiple ticks. + var updateCount = Exts.IntegerDivisionRoundingAwayFromZero(squadsPendingUpdate.Count, attackForceTicks); + for (var i = 0; i < updateCount; i++) + { + var squadPendingUpdate = squadsPendingUpdate.Pop(); + if (squadPendingUpdate.IsValid) + squadPendingUpdate.Update(); } if (--assignRolesTicks <= 0)