namespace MoonlightServers.Daemon.Helpers; public partial class SystemMetrics { /// Memory figures derived from /proc/meminfo. /// Physical RAM installed. /// RAM actively in use (Total - Available). /// Completely unallocated RAM. /// Page cache + reclaimable slab — matches the cached column in free -h. /// Kernel I/O buffer memory. /// Estimated RAM available for new allocations without swapping. /// UsedBytes / TotalBytes as a percentage (0–100). public record MemoryInfo( long TotalBytes, long UsedBytes, long FreeBytes, long CachedBytes, long BuffersBytes, long AvailableBytes, double UsedPercent ); // Memory — /proc/meminfo /// /// Parses /proc/meminfo into a record. /// The CachedBytes field is computed as /// Cached + SReclaimable - Shmem to match the value shown by free -h. /// private static async Task ReadMemoryAsync() { var lines = await File.ReadAllLinesAsync("/proc/meminfo"); var map = new Dictionary(StringComparer.Ordinal); foreach (var line in lines) { var colon = line.IndexOf(':'); if (colon < 0) continue; var key = line[..colon].Trim(); var val = line[(colon + 1)..].Trim().Split(' ')[0]; // Strip "kB" suffix. if (long.TryParse(val, out var kb)) map[key] = kb * 1024L; } var total = map.GetValueOrDefault("MemTotal"); var available = map.GetValueOrDefault("MemAvailable"); var free = map.GetValueOrDefault("MemFree"); var buffers = map.GetValueOrDefault("Buffers"); var cached = map.GetValueOrDefault("Cached") + map.GetValueOrDefault("SReclaimable") - map.GetValueOrDefault("Shmem"); var used = total - available; var usedPct = total > 0 ? Math.Round((double)used / total * 100.0, 2) : 0.0; return new MemoryInfo(total, used, free, cached, buffers, available, usedPct); } }