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#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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; }
}
}
}