Files
BarotraumaModServer/LocalMods/Enhanced Loading/CSharp/Client/MemoryManager.cs

88 lines
2.5 KiBLFS
C#
Executable File

using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime;
using Barotrauma;
using Microsoft.Xna.Framework;
using HarmonyLib;
namespace FastLoadMod
{
public class MemoryManager : IAssemblyPlugin
{
private static Harmony harmony;
private static GCLatencyMode originalLatencyMode;
private static bool isManagingMemory = false;
private static Stopwatch pacemakerTimer = new Stopwatch();
private const double PACEMAKER_INTERVAL_MS = 50.0;
public void Initialize()
{
harmony = new Harmony("com.fastload.memorymanager");
try
{
var updateMethod = typeof(GameMain).GetMethod("Update", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (updateMethod != null)
{
harmony.Patch(updateMethod, postfix: new HarmonyMethod(AccessTools.Method(typeof(MemoryManager), "PacemakerUpdate")));
}
var generateMethod = typeof(Level).GetMethod("Generate", BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance);
if (generateMethod != null)
{
harmony.Patch(generateMethod,
prefix: new HarmonyMethod(AccessTools.Method(typeof(MemoryManager), "StartControlledBurn")),
postfix: new HarmonyMethod(AccessTools.Method(typeof(MemoryManager), "EndControlledBurn")));
}
DebugConsole.NewMessage("[EnLo] MemManager working.", Color.Lime);
}
catch (Exception ex)
{
DebugConsole.NewMessage($"[EnLo] Memory Manager Error: {ex.Message}", Color.Red);
}
}
public void Dispose()
{
if (isManagingMemory) EndControlledBurn();
if (harmony != null)
{
harmony.UnpatchSelf();
harmony = null;
}
}
public void OnLoadCompleted() { }
public void PreInitPatching() { }
public static void StartControlledBurn()
{
if (!isManagingMemory)
{
originalLatencyMode = GCSettings.LatencyMode;
GCSettings.LatencyMode = GCLatencyMode.SustainedLowLatency;
isManagingMemory = true;
pacemakerTimer.Restart();
}
}
public static void PacemakerUpdate()
{
if (!isManagingMemory) return;
if (pacemakerTimer.Elapsed.TotalMilliseconds >= PACEMAKER_INTERVAL_MS)
{
GC.Collect(0, GCCollectionMode.Optimized, false, false);
pacemakerTimer.Restart();
}
}
public static void EndControlledBurn()
{
if (isManagingMemory)
{
pacemakerTimer.Stop();
GCSettings.LatencyMode = originalLatencyMode;
isManagingMemory = false;
GC.Collect(2, GCCollectionMode.Forced, true, true);
}
}
}
}