using System.Diagnostics; using System.Runtime.InteropServices; using SpdUp.Core; namespace SpdUp.Services; /// /// Performs real memory optimizations: working-set trimming + standby-list purge. /// Requires administrator privileges. /// public sealed class RamOptimizationService { /// /// Trim working sets of all accessible processes – pushes unused pages to the standby list. /// public RamCleanupResult TrimWorkingSets() { int trimmed = 0, failed = 0; var ownPid = Environment.ProcessId; foreach (var proc in Process.GetProcesses()) { try { if (proc.Id == ownPid || proc.Id == 0 || proc.Id == 4) continue; var hProcess = NativeMethods.OpenProcess( NativeMethods.PROCESS_SET_INFORMATION | NativeMethods.PROCESS_QUERY_INFORMATION, false, proc.Id); if (hProcess == IntPtr.Zero) { failed++; continue; } try { if (NativeMethods.EmptyWorkingSet(hProcess)) trimmed++; else failed++; } finally { NativeMethods.CloseHandle(hProcess); } } catch { failed++; } finally { proc.Dispose(); } } Logger.Info($"Working-set trim complete: {trimmed} trimmed, {failed} skipped."); return new RamCleanupResult(trimmed, failed, 0); } /// /// Purge the standby memory list. Requires SeProfileSingleProcessPrivilege. /// public bool PurgeStandbyList() { try { NativeMethods.EnablePrivilege(NativeMethods.SE_PROF_SINGLE_PROCESS_NAME); int command = (int)NativeMethods.SYSTEM_MEMORY_LIST_COMMAND.MemoryPurgeStandbyList; int status = NativeMethods.NtSetSystemInformation( NativeMethods.SystemMemoryListInformation, ref command, Marshal.SizeOf()); if (status == 0) { Logger.Info("Standby list purged successfully."); return true; } Logger.Warn($"NtSetSystemInformation returned NTSTATUS 0x{status:X8}"); return false; } catch (Exception ex) { Logger.Error("Failed to purge standby list", ex); return false; } } /// /// Full RAM optimisation: trim working sets + purge standby. /// public RamCleanupResult FullCleanup() { var result = TrimWorkingSets(); var purged = PurgeStandbyList(); return result with { StandbyPurged = purged ? 1 : 0 }; } /// /// Returns current memory statistics. /// public static (ulong totalMB, ulong availMB, uint loadPercent) GetMemoryStatus() { var mem = new NativeMethods.MEMORYSTATUSEX { dwLength = (uint)Marshal.SizeOf() }; NativeMethods.GlobalMemoryStatusEx(ref mem); return (mem.ullTotalPhys / 1048576, mem.ullAvailPhys / 1048576, mem.dwMemoryLoad); } } public record struct RamCleanupResult(int TrimmedCount, int FailedCount, int StandbyPurged);