]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Add a new gas React() benchmark (#41202)
authorKryyto <69859497+Kryyto@users.noreply.github.com>
Fri, 31 Oct 2025 00:05:31 +0000 (01:05 +0100)
committerGitHub <noreply@github.com>
Fri, 31 Oct 2025 00:05:31 +0000 (00:05 +0000)
* Add a new gas React() benchmark

* fix the iteration amount to 100, remove unused using

* fix the iteration amount to 1000

Content.Benchmarks/GasReactionBenchmark.cs [new file with mode: 0644]

diff --git a/Content.Benchmarks/GasReactionBenchmark.cs b/Content.Benchmarks/GasReactionBenchmark.cs
new file mode 100644 (file)
index 0000000..9ed3037
--- /dev/null
@@ -0,0 +1,253 @@
+using System.Threading.Tasks;
+using BenchmarkDotNet.Attributes;
+using Content.IntegrationTests;
+using Content.IntegrationTests.Pair;
+using Content.Server.Atmos;
+using Content.Server.Atmos.EntitySystems;
+using Content.Server.Atmos.Reactions;
+using Content.Shared.Atmos;
+using Robust.Shared;
+using Robust.Shared.Analyzers;
+using Robust.Shared.GameObjects;
+using Robust.Shared.Maths;
+
+namespace Content.Benchmarks;
+
+/// <summary>
+/// Benchmarks the performance of different gas reactions.
+/// Tests each reaction type with realistic gas mixtures to measure computational cost.
+/// </summary>
+[Virtual]
+[GcServer(true)]
+[MemoryDiagnoser]
+public class GasReactionBenchmark
+{
+    private const int Iterations = 1000;
+    private TestPair _pair = default!;
+    private AtmosphereSystem _atmosphereSystem = default!;
+
+    // Grid and tile for reactions that need a holder
+    private EntityUid _testGrid = default!;
+    private TileAtmosphere _testTile = default!;
+    // Reaction instances
+    private PlasmaFireReaction _plasmaFireReaction = default!;
+    private TritiumFireReaction _tritiumFireReaction = default!;
+    private FrezonProductionReaction _frezonProductionReaction = default!;
+    private FrezonCoolantReaction _frezonCoolantReaction = default!;
+    private AmmoniaOxygenReaction _ammoniaOxygenReaction = default!;
+    private N2ODecompositionReaction _n2oDecompositionReaction = default!;
+    private WaterVaporReaction _waterVaporReaction = default!;
+    // Gas mixtures for each reaction type
+    private GasMixture _plasmaFireMixture = default!;
+    private GasMixture _tritiumFireMixture = default!;
+    private GasMixture _frezonProductionMixture = default!;
+    private GasMixture _frezonCoolantMixture = default!;
+    private GasMixture _ammoniaOxygenMixture = default!;
+    private GasMixture _n2oDecompositionMixture = default!;
+    private GasMixture _waterVaporMixture = default!;
+
+    [GlobalSetup]
+    public async Task SetupAsync()
+    {
+        ProgramShared.PathOffset = "../../../../";
+        PoolManager.Startup();
+        _pair = await PoolManager.GetServerClient();
+        var server = _pair.Server;
+
+        // Create test map and grid
+        var mapData = await _pair.CreateTestMap();
+        _testGrid = mapData.Grid;
+
+        await server.WaitPost(() =>
+        {
+            var entMan = server.ResolveDependency<IEntityManager>();
+            _atmosphereSystem = entMan.System<AtmosphereSystem>();
+
+            _plasmaFireReaction = new PlasmaFireReaction();
+            _tritiumFireReaction = new TritiumFireReaction();
+            _frezonProductionReaction = new FrezonProductionReaction();
+            _frezonCoolantReaction = new FrezonCoolantReaction();
+            _ammoniaOxygenReaction = new AmmoniaOxygenReaction();
+            _n2oDecompositionReaction = new N2ODecompositionReaction();
+            _waterVaporReaction = new WaterVaporReaction();
+
+            SetupGasMixtures();
+            SetupTile();
+        });
+    }
+
+    private void SetupGasMixtures()
+    {
+        // Plasma Fire: Plasma + Oxygen at high temperature
+        // Temperature must be > PlasmaMinimumBurnTemperature for reaction to occur
+        _plasmaFireMixture = new GasMixture(Atmospherics.CellVolume)
+        {
+            Temperature = Atmospherics.PlasmaMinimumBurnTemperature + 100f // ~673K
+        };
+        _plasmaFireMixture.AdjustMoles(Gas.Plasma, 20f);
+        _plasmaFireMixture.AdjustMoles(Gas.Oxygen, 100f);
+
+        // Tritium Fire: Tritium + Oxygen at high temperature
+        // Temperature must be > FireMinimumTemperatureToExist for reaction to occur
+        _tritiumFireMixture = new GasMixture(Atmospherics.CellVolume)
+        {
+            Temperature = Atmospherics.FireMinimumTemperatureToExist + 100f // ~473K
+        };
+        _tritiumFireMixture.AdjustMoles(Gas.Tritium, 20f);
+        _tritiumFireMixture.AdjustMoles(Gas.Oxygen, 100f);
+
+        // Frezon Production: Oxygen + Tritium + Nitrogen catalyst
+        // Optimal temperature for efficiency (80% of max efficiency temp)
+        _frezonProductionMixture = new GasMixture(Atmospherics.CellVolume)
+        {
+            Temperature = Atmospherics.FrezonProductionMaxEfficiencyTemperature * 0.8f // ~48K
+        };
+        _frezonProductionMixture.AdjustMoles(Gas.Oxygen, 50f);
+        _frezonProductionMixture.AdjustMoles(Gas.Tritium, 50f);
+        _frezonProductionMixture.AdjustMoles(Gas.Nitrogen, 10f);
+
+        // Frezon Coolant: Frezon + Nitrogen
+        // Temperature must be > FrezonCoolLowerTemperature (23.15K) for reaction to occur
+        _frezonCoolantMixture = new GasMixture(Atmospherics.CellVolume)
+        {
+            Temperature = Atmospherics.T20C + 50f // ~343K
+        };
+        _frezonCoolantMixture.AdjustMoles(Gas.Frezon, 30f);
+        _frezonCoolantMixture.AdjustMoles(Gas.Nitrogen, 100f);
+
+        // Ammonia + Oxygen reaction (concentration-dependent, no temp requirement)
+        _ammoniaOxygenMixture = new GasMixture(Atmospherics.CellVolume)
+        {
+            Temperature = Atmospherics.T20C + 100f // ~393K
+        };
+        _ammoniaOxygenMixture.AdjustMoles(Gas.Ammonia, 40f);
+        _ammoniaOxygenMixture.AdjustMoles(Gas.Oxygen, 40f);
+
+        // N2O Decomposition (no temperature requirement, just needs N2O moles)
+        _n2oDecompositionMixture = new GasMixture(Atmospherics.CellVolume)
+        {
+            Temperature = Atmospherics.T20C + 100f // ~393K
+        };
+        _n2oDecompositionMixture.AdjustMoles(Gas.NitrousOxide, 100f);
+
+        // Water Vapor - needs water vapor to condense
+        _waterVaporMixture = new GasMixture(Atmospherics.CellVolume)
+        {
+            Temperature = Atmospherics.T20C
+        };
+        _waterVaporMixture.AdjustMoles(Gas.WaterVapor, 50f);
+    }
+
+    private void SetupTile()
+    {
+        // Create a tile atmosphere to use as holder for all reactions
+        var testIndices = new Vector2i(0, 0);
+        _testTile = new TileAtmosphere(_testGrid, testIndices, new GasMixture(Atmospherics.CellVolume)
+        {
+            Temperature = Atmospherics.T20C
+        });
+    }
+
+    private static GasMixture CloneMixture(GasMixture original)
+    {
+        return new GasMixture(original);
+    }
+
+    [Benchmark]
+    public async Task PlasmaFireReaction()
+    {
+        await _pair.Server.WaitPost(() =>
+        {
+            for (var i = 0; i < Iterations; i++)
+            {
+                var mixture = CloneMixture(_plasmaFireMixture);
+                _plasmaFireReaction.React(mixture, _testTile, _atmosphereSystem, 1f);
+            }
+        });
+    }
+
+    [Benchmark]
+    public async Task TritiumFireReaction()
+    {
+        await _pair.Server.WaitPost(() =>
+        {
+            for (var i = 0; i < Iterations; i++)
+            {
+                var mixture = CloneMixture(_tritiumFireMixture);
+                _tritiumFireReaction.React(mixture, _testTile, _atmosphereSystem, 1f);
+            }
+        });
+    }
+
+    [Benchmark]
+    public async Task FrezonProductionReaction()
+    {
+        await _pair.Server.WaitPost(() =>
+        {
+            for (var i = 0; i < Iterations; i++)
+            {
+                var mixture = CloneMixture(_frezonProductionMixture);
+                _frezonProductionReaction.React(mixture, _testTile, _atmosphereSystem, 1f);
+            }
+        });
+    }
+
+    [Benchmark]
+    public async Task FrezonCoolantReaction()
+    {
+        await _pair.Server.WaitPost(() =>
+        {
+            for (var i = 0; i < Iterations; i++)
+            {
+                var mixture = CloneMixture(_frezonCoolantMixture);
+                _frezonCoolantReaction.React(mixture, _testTile, _atmosphereSystem, 1f);
+            }
+        });
+    }
+
+    [Benchmark]
+    public async Task AmmoniaOxygenReaction()
+    {
+        await _pair.Server.WaitPost(() =>
+        {
+            for (var i = 0; i < Iterations; i++)
+            {
+                var mixture = CloneMixture(_ammoniaOxygenMixture);
+                _ammoniaOxygenReaction.React(mixture, _testTile, _atmosphereSystem, 1f);
+            }
+        });
+    }
+
+    [Benchmark]
+    public async Task N2ODecompositionReaction()
+    {
+        await _pair.Server.WaitPost(() =>
+        {
+            for (var i = 0; i < Iterations; i++)
+            {
+                var mixture = CloneMixture(_n2oDecompositionMixture);
+                _n2oDecompositionReaction.React(mixture, _testTile, _atmosphereSystem, 1f);
+            }
+        });
+    }
+
+    [Benchmark]
+    public async Task WaterVaporReaction()
+    {
+        await _pair.Server.WaitPost(() =>
+        {
+            for (var i = 0; i < Iterations; i++)
+            {
+                var mixture = CloneMixture(_waterVaporMixture);
+                _waterVaporReaction.React(mixture, _testTile, _atmosphereSystem, 1f);
+            }
+        });
+    }
+
+    [GlobalCleanup]
+    public async Task CleanupAsync()
+    {
+        await _pair.DisposeAsync();
+        PoolManager.Shutdown();
+    }
+}