You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

179 lines
6.2 KiB
C#

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace SocketExample
{
public static class MemoryManager
{
private static readonly object _lock = new object();
private static DateTime _lastCleanupTime = DateTime.MinValue;
private static Timer _cleanupTimer;
/// <summary>
/// 初始化内存管理器
/// </summary>
/// <param name="cleanupIntervalMinutes">清理间隔(分钟)</param>
public static void Initialize(int cleanupIntervalMinutes = 5)
{
// 创建定时清理任务
_cleanupTimer = new Timer(CleanupCallback, null,
TimeSpan.FromMinutes(cleanupIntervalMinutes),
TimeSpan.FromMinutes(cleanupIntervalMinutes));
Console.WriteLine($"MemoryManager已启动每{cleanupIntervalMinutes}分钟检查一次内存");
}
/// <summary>
/// 立即清理内存
/// </summary>
/// <param name="aggressive">是否激进清理包括第2代</param>
public static void ForceCleanup(bool aggressive = false)
{
lock (_lock)
{
try
{
long before = GC.GetTotalMemory(true);
Console.WriteLine($"清理前内存: {FormatBytes(before)}");
if (aggressive)
{
// 激进模式:清理所有代
GC.Collect(2, GCCollectionMode.Forced);
GC.WaitForPendingFinalizers();
GC.Collect();
}
else
{
// 温和模式只清理第0代和第1代
GC.Collect(0, GCCollectionMode.Optimized);
GC.Collect(1, GCCollectionMode.Optimized);
}
long after = GC.GetTotalMemory(true);
Console.WriteLine($"清理后内存: {FormatBytes(after)}");
Console.WriteLine($"释放了: {FormatBytes(before - after)}");
_lastCleanupTime = DateTime.Now;
}
catch (Exception ex)
{
Console.WriteLine($"内存清理失败: {ex.Message}");
}
}
}
/// <summary>
/// 智能清理 - 根据内存使用情况决定清理策略
/// </summary>
public static void SmartCleanup()
{
var memoryInfo = GetMemoryInfo();
Console.WriteLine($"当前内存使用: {memoryInfo.UsagePercentage:F1}% ({memoryInfo.ProcessMemoryMB:F1}MB)");
if (memoryInfo.UsagePercentage > 85)
{
Console.WriteLine("内存使用超过85%,执行深度清理...");
ForceCleanup(true); // 激进清理
}
else if (memoryInfo.UsagePercentage > 70)
{
Console.WriteLine("内存使用超过70%,执行普通清理...");
ForceCleanup(false); // 普通清理
}
else if (memoryInfo.UsagePercentage > 50 &&
DateTime.Now - _lastCleanupTime > TimeSpan.FromMinutes(10))
{
Console.WriteLine("内存使用较高且超过10分钟未清理执行轻度清理...");
ForceCleanup(false);
}
else
{
Console.WriteLine("内存使用正常,跳过清理");
}
}
/// <summary>
/// 获取内存信息
/// </summary>
public static MemoryInfo GetMemoryInfo()
{
var process = Process.GetCurrentProcess();
process.Refresh();
long processMemory = process.WorkingSet64;
//long totalPhysicalMemory = GetTotalPhysicalMemory();
return new MemoryInfo
{
ProcessMemoryBytes = processMemory,
ProcessMemoryMB = processMemory / 1024.0 / 1024.0,
Gen0Collections = GC.CollectionCount(0),
Gen1Collections = GC.CollectionCount(1),
Gen2Collections = GC.CollectionCount(2)
};
}
/// <summary>
/// 监控内存使用,超过阈值自动清理
/// </summary>
public static void StartMonitoring(int thresholdMB = 100, int checkIntervalSeconds = 30)
{
Task.Run(async () =>
{
while (true)
{
await Task.Delay(TimeSpan.FromSeconds(checkIntervalSeconds));
var info = GetMemoryInfo();
if (info.ProcessMemoryMB > thresholdMB)
{
Console.WriteLine($"内存使用超过{thresholdMB}MB当前{info.ProcessMemoryMB:F1}MB触发自动清理...");
SmartCleanup();
}
}
});
}
private static void CleanupCallback(object state)
{
Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] 定时内存检查...");
SmartCleanup();
}
private static string FormatBytes(long bytes)
{
string[] suffixes = { "B", "KB", "MB", "GB" };
int suffixIndex = 0;
double number = bytes;
while (number >= 1024 && suffixIndex < suffixes.Length - 1)
{
number /= 1024;
suffixIndex++;
}
return $"{number:F2} {suffixes[suffixIndex]}";
}
public class MemoryInfo
{
public long ProcessMemoryBytes { get; set; }
public double ProcessMemoryMB { get; set; }
public long TotalPhysicalMemoryBytes { get; set; }
public double TotalPhysicalMemoryMB { get; set; }
public double UsagePercentage { get; set; }
public int Gen0Collections { get; set; }
public int Gen1Collections { get; set; }
public int Gen2Collections { get; set; }
}
}
}