mirror of
https://github.com/SoPat712/allstarr.git
synced 2026-02-10 07:58:39 -05:00
Add GC hints to prevent memory leaks from large byte arrays
This commit is contained in:
@@ -1911,23 +1911,36 @@ public class AdminController : ControllerBase
|
||||
{
|
||||
try
|
||||
{
|
||||
// Get memory stats BEFORE GC
|
||||
var memoryBeforeGC = GC.GetTotalMemory(false);
|
||||
var gen0Before = GC.CollectionCount(0);
|
||||
var gen1Before = GC.CollectionCount(1);
|
||||
var gen2Before = GC.CollectionCount(2);
|
||||
|
||||
// Force garbage collection to get accurate numbers
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
GC.Collect();
|
||||
|
||||
var memoryUsage = GC.GetTotalMemory(false);
|
||||
var gen0 = GC.CollectionCount(0);
|
||||
var gen1 = GC.CollectionCount(1);
|
||||
var gen2 = GC.CollectionCount(2);
|
||||
var memoryAfterGC = GC.GetTotalMemory(false);
|
||||
var gen0After = GC.CollectionCount(0);
|
||||
var gen1After = GC.CollectionCount(1);
|
||||
var gen2After = GC.CollectionCount(2);
|
||||
|
||||
// Get process memory info
|
||||
var process = System.Diagnostics.Process.GetCurrentProcess();
|
||||
|
||||
return Ok(new {
|
||||
Timestamp = DateTime.UtcNow,
|
||||
GCMemoryBytes = memoryUsage,
|
||||
GCMemoryMB = Math.Round(memoryUsage / (1024.0 * 1024.0), 2),
|
||||
BeforeGC = new {
|
||||
GCMemoryBytes = memoryBeforeGC,
|
||||
GCMemoryMB = Math.Round(memoryBeforeGC / (1024.0 * 1024.0), 2)
|
||||
},
|
||||
AfterGC = new {
|
||||
GCMemoryBytes = memoryAfterGC,
|
||||
GCMemoryMB = Math.Round(memoryAfterGC / (1024.0 * 1024.0), 2)
|
||||
},
|
||||
MemoryFreedMB = Math.Round((memoryBeforeGC - memoryAfterGC) / (1024.0 * 1024.0), 2),
|
||||
ProcessWorkingSetBytes = process.WorkingSet64,
|
||||
ProcessWorkingSetMB = Math.Round(process.WorkingSet64 / (1024.0 * 1024.0), 2),
|
||||
ProcessPrivateMemoryBytes = process.PrivateMemorySize64,
|
||||
@@ -1935,9 +1948,15 @@ public class AdminController : ControllerBase
|
||||
ProcessVirtualMemoryBytes = process.VirtualMemorySize64,
|
||||
ProcessVirtualMemoryMB = Math.Round(process.VirtualMemorySize64 / (1024.0 * 1024.0), 2),
|
||||
GCCollections = new {
|
||||
Gen0 = gen0,
|
||||
Gen1 = gen1,
|
||||
Gen2 = gen2
|
||||
Gen0Before = gen0Before,
|
||||
Gen0After = gen0After,
|
||||
Gen0Triggered = gen0After - gen0Before,
|
||||
Gen1Before = gen1Before,
|
||||
Gen1After = gen1After,
|
||||
Gen1Triggered = gen1After - gen1Before,
|
||||
Gen2Before = gen2Before,
|
||||
Gen2After = gen2After,
|
||||
Gen2Triggered = gen2After - gen2Before
|
||||
},
|
||||
GCMode = GCSettings.IsServerGC ? "Server" : "Workstation",
|
||||
GCLatencyMode = GCSettings.LatencyMode.ToString()
|
||||
@@ -1948,6 +1967,54 @@ public class AdminController : ControllerBase
|
||||
return BadRequest(new { error = ex.Message });
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Forces garbage collection to free up memory (emergency use only).
|
||||
/// </summary>
|
||||
[HttpPost("force-gc")]
|
||||
public IActionResult ForceGarbageCollection()
|
||||
{
|
||||
try
|
||||
{
|
||||
var memoryBefore = GC.GetTotalMemory(false);
|
||||
var processBefore = System.Diagnostics.Process.GetCurrentProcess().WorkingSet64;
|
||||
|
||||
// Force full garbage collection
|
||||
GC.Collect(2, GCCollectionMode.Forced);
|
||||
GC.WaitForPendingFinalizers();
|
||||
GC.Collect(2, GCCollectionMode.Forced);
|
||||
|
||||
var memoryAfter = GC.GetTotalMemory(false);
|
||||
var processAfter = System.Diagnostics.Process.GetCurrentProcess().WorkingSet64;
|
||||
|
||||
return Ok(new {
|
||||
Timestamp = DateTime.UtcNow,
|
||||
MemoryFreedMB = Math.Round((memoryBefore - memoryAfter) / (1024.0 * 1024.0), 2),
|
||||
ProcessMemoryFreedMB = Math.Round((processBefore - processAfter) / (1024.0 * 1024.0), 2),
|
||||
BeforeGCMB = Math.Round(memoryBefore / (1024.0 * 1024.0), 2),
|
||||
AfterGCMB = Math.Round(memoryAfter / (1024.0 * 1024.0), 2),
|
||||
BeforeProcessMB = Math.Round(processBefore / (1024.0 * 1024.0), 2),
|
||||
AfterProcessMB = Math.Round(processAfter / (1024.0 * 1024.0), 2)
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return BadRequest(new { error = ex.Message });
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to trigger GC after large file operations to prevent memory leaks.
|
||||
/// </summary>
|
||||
private static void TriggerGCAfterLargeOperation(int sizeInBytes)
|
||||
{
|
||||
// Only trigger GC for files larger than 1MB to avoid performance impact
|
||||
if (sizeInBytes > 1024 * 1024)
|
||||
{
|
||||
// Suggest GC collection for large objects (they go to LOH and aren't collected as frequently)
|
||||
GC.Collect(2, GCCollectionMode.Optimized, blocking: false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class ConfigUpdateRequest
|
||||
|
||||
Reference in New Issue
Block a user