From 7e899d900ac7300c77737629065d7190ea678061 Mon Sep 17 00:00:00 2001 From: NotAlwaysTrue <2136846186@qq.com> Date: Sat, 27 Dec 2025 13:19:36 +0800 Subject: [PATCH] Added ClientCount for PerformenceMonitor Add a marker to help distinguish EP from other SV Executables Fixed a "Failed to copy object. Source is null." introduced by last update Uses dynamic ThreadCount instead of fixed 16 Re-Removed most PF support Re-Parallelzed Level update and Character Update(a conflict warning will be issued --- .../ServerSource/PerformenceMonitor.cs | 5 ++ .../BarotraumaServer/ServerSource/Program.cs | 2 +- .../Map/Levels/LevelObjects/LevelTrigger.cs | 2 +- .../SharedSource/Map/MapEntity.cs | 85 +++++++------------ .../SharedSource/Screens/GameScreen.cs | 41 ++++----- 5 files changed, 57 insertions(+), 78 deletions(-) diff --git a/Barotrauma/BarotraumaServer/ServerSource/PerformenceMonitor.cs b/Barotrauma/BarotraumaServer/ServerSource/PerformenceMonitor.cs index d6d4c5d8d..9186bd504 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/PerformenceMonitor.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/PerformenceMonitor.cs @@ -37,6 +37,10 @@ namespace Barotrauma { get { return PhysicsBody.List.Count; } } + public int ConnectClients + { + get { return Client.ClientList.Count; } + } public double RealTickRate { @@ -160,6 +164,7 @@ namespace Barotrauma return $"Server Performence Info \n" + $"Item Count: {ItemCount}\n" + $"Character Count: {CharacterCount}\n" + + $"Clients Count {ConnectClients}\n " + $"PhysicsBody Count: {PhysicsBodyCount}\n" + $"Tick Rate: {RealTickRate}\n" + $"Min Tick Rate: {TickRateLow}\n" + diff --git a/Barotrauma/BarotraumaServer/ServerSource/Program.cs b/Barotrauma/BarotraumaServer/ServerSource/Program.cs index 35e2503ef..1f5a9727b 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Program.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Program.cs @@ -64,7 +64,7 @@ namespace Barotrauma GameMain.ShouldRun = false; }; #endif - Console.WriteLine("Barotrauma Dedicated Server " + GameMain.Version + + Console.WriteLine("Barotrauma Dedicated Server(EP) " + GameMain.Version + " (" + AssemblyInfo.BuildString + ", branch " + AssemblyInfo.GitBranch + ", revision " + AssemblyInfo.GitRevision + ")"); if (Console.IsOutputRedirected) { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/LevelObjects/LevelTrigger.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/LevelObjects/LevelTrigger.cs index b05cc6be7..261a21706 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/LevelObjects/LevelTrigger.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/LevelObjects/LevelTrigger.cs @@ -479,7 +479,7 @@ namespace Barotrauma { foreach (Fixture fixture in triggerBody.FarseerBody.FixtureList) { - ContactEdge contactEdge = fixture.Body.ContactList.CreateCopy(); + ContactEdge contactEdge = fixture.Body.ContactList == null ? null: fixture.Body.ContactList.CreateCopy(); while (contactEdge != null) { if (contactEdge.Contact != null && diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/MapEntity.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/MapEntity.cs index 48ea30861..2634f9560 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/MapEntity.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/MapEntity.cs @@ -642,44 +642,34 @@ namespace Barotrauma /// public static void UpdateAll(float deltaTime, Camera cam , ParallelOptions parallelOptions) { - mapEntityUpdateTick++; #if CLIENT var sw = new System.Diagnostics.Stopwatch(); sw.Start(); #endif - bool shouldUpdateMapEntities = mapEntityUpdateTick % MapEntityUpdateInterval == 0; - bool shouldUpdatePower = mapEntityUpdateTick % PoweredUpdateInterval == 0; - // Buffer lists to avoid repeated allocations - var hullList = shouldUpdateMapEntities ? Hull.HullList.ToList() : null; - var structureList = shouldUpdateMapEntities ? Structure.WallList.ToList() : null; + var hullList = Hull.HullList.ToList(); + var structureList = Structure.WallList.ToList(); var gapList = Gap.GapList.ToList(); - var itemList = shouldUpdateMapEntities ? Item.ItemList.ToList() : null; + var itemList = Item.ItemList.ToList(); // First phase: parallel updates that have no order dependencies Parallel.Invoke(parallelOptions, // Hull parallel update () => { - if (shouldUpdateMapEntities && hullList != null) + Parallel.ForEach(hullList, parallelOptions, hull => { - Parallel.ForEach(hullList, parallelOptions, hull => - { - hull.Update(deltaTime * MapEntityUpdateInterval, cam); - }); - } + hull.Update(deltaTime, cam); + }); }, // Structure parallel update () => { - if (shouldUpdateMapEntities && structureList != null) + Parallel.ForEach(structureList, parallelOptions, structure => { - Parallel.ForEach(structureList, parallelOptions, structure => - { - structure.Update(deltaTime * MapEntityUpdateInterval, cam); - }); - } + structure.Update(deltaTime, cam); + }); }, // Gap reset (must be done before update) () => @@ -692,27 +682,21 @@ namespace Barotrauma // Powered components update () => { - if (shouldUpdatePower) - { - Powered.UpdatePower(deltaTime * PoweredUpdateInterval); - } + Powered.UpdatePower(deltaTime); } ); #if CLIENT // Hull Cheats need to be executed after Hull update - if (shouldUpdateMapEntities) - { - Hull.UpdateCheats(deltaTime * MapEntityUpdateInterval, cam); - } + Hull.UpdateCheats(deltaTime, cam); #endif // Gap update (has order dependencies, keep random order but execute sequentially) var shuffledGaps = gapList.OrderBy(g => Rand.Int(int.MaxValue)).ToList(); - foreach (Gap gap in shuffledGaps) + Parallel.ForEach(gapList, parallelOptions, gap => { gap.Update(deltaTime, cam); - } + }); #if CLIENT sw.Stop(); @@ -721,33 +705,30 @@ namespace Barotrauma #endif // Item update (Item.Update() is not thread-safe and must be executed on the main thread) - if (shouldUpdateMapEntities && itemList != null) + Item.UpdatePendingConditionUpdates(deltaTime); + + float scaledDeltaTime = deltaTime * MapEntityUpdateInterval; + Item lastUpdatedItem = null; + + try { - Item.UpdatePendingConditionUpdates(deltaTime); - - float scaledDeltaTime = deltaTime * MapEntityUpdateInterval; - Item lastUpdatedItem = null; - - try + foreach (Item item in itemList) { - foreach (Item item in itemList) - { - lastUpdatedItem = item; - item.Update(scaledDeltaTime, cam); - } + lastUpdatedItem = item; + item.Update(scaledDeltaTime, cam); } - catch (InvalidOperationException e) - { - GameAnalyticsManager.AddErrorEventOnce( - "MapEntity.UpdateAll:ItemUpdateInvalidOperation", - GameAnalyticsManager.ErrorSeverity.Critical, - $"Error while updating item {lastUpdatedItem?.Name ?? "null"}: {e.Message}"); - throw new InvalidOperationException($"Error while updating item {lastUpdatedItem?.Name ?? "null"}", innerException: e); - } - - UpdateAllProjSpecific(scaledDeltaTime); - Spawner?.Update(); } + catch (InvalidOperationException e) + { + GameAnalyticsManager.AddErrorEventOnce( + "MapEntity.UpdateAll:ItemUpdateInvalidOperation", + GameAnalyticsManager.ErrorSeverity.Critical, + $"Error while updating item {lastUpdatedItem?.Name ?? "null"}: {e.Message}"); + throw new InvalidOperationException($"Error while updating item {lastUpdatedItem?.Name ?? "null"}", innerException: e); + } + + UpdateAllProjSpecific(scaledDeltaTime); + Spawner?.Update(); #if CLIENT sw.Stop(); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Screens/GameScreen.cs b/Barotrauma/BarotraumaShared/SharedSource/Screens/GameScreen.cs index 00bb104ba..182873fc1 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Screens/GameScreen.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Screens/GameScreen.cs @@ -7,6 +7,7 @@ using FarseerPhysics; using System.Threading.Tasks; using System.Linq; using System.Collections.Generic; +using System; #if DEBUG && CLIENT @@ -24,7 +25,7 @@ namespace Barotrauma private static readonly ParallelOptions parallelOptions = new ParallelOptions { - MaxDegreeOfParallelism = 16 + MaxDegreeOfParallelism = Environment.ProcessorCount * 2, }; #if CLIENT @@ -151,31 +152,23 @@ namespace Barotrauma var physicsBodies = PhysicsBody.List.ToList(); - Parallel.Invoke(parallelOptions, - () => + Parallel.ForEach(physicsBodies, parallelOptions, body => + { + if ((body.Enabled || body.UserData is Character) && + body.BodyType != BodyType.Static) { - Parallel.ForEach(physicsBodies, parallelOptions, body => - { - if ((body.Enabled || body.UserData is Character) && - body.BodyType != BodyType.Static) - { - body.Update(); - } - }); - }, - () => - { - GameMain.GameSession?.Update((float)deltaTime); + body.Update(); } - ); + }); + GameMain.GameSession?.Update((float)deltaTime); - foreach (PhysicsBody body in physicsBodies) + Parallel.ForEach(physicsBodies, parallelOptions, body => { if (body.Enabled && body.BodyType != BodyType.Static) { body.SetPrevTransform(body.SimPosition, body.Rotation); } - } + }); MapEntity.ClearHighlightedEntities(); @@ -252,14 +245,14 @@ namespace Barotrauma Character.Controlled?.UpdateLocalCursor(cam); #elif SERVER - if (Level.Loaded != null) - { - Level.Loaded.Update((float)deltaTime, Camera.Instance); - } - Character.UpdateAll((float)deltaTime, Camera.Instance); + Parallel.Invoke(parallelOptions, + () => { if (Level.Loaded != null) Level.Loaded.Update((float)deltaTime, Camera.Instance); }, + () => Character.UpdateAll((float)deltaTime, Camera.Instance) + ); #endif var submarines = Submarine.Loaded.ToList(); + Parallel.ForEach(submarines, parallelOptions, sub => { sub.SetPrevTransform(sub.Position); @@ -277,8 +270,8 @@ namespace Barotrauma MapEntity.UpdateAll((float)deltaTime, cam, parallelOptions); #elif SERVER - MapEntity.UpdateAll((float)deltaTime, Camera.Instance, parallelOptions); + //StatusEffect.UpdateAll is not thread-safe and must be executed on the main thread StatusEffect.UpdateAll((float)deltaTime);