using System;
using System.IO;
using System.Runtime.InteropServices;
namespace ModpackLauncher.Services;
public static class SystemInfo
{
private const long DefaultFallbackKB = 8L * 1024 * 1024; // assume 8 GB if detection fails
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetPhysicallyInstalledSystemMemory(out long memoryInKilobytes);
/// Total physically installed system RAM in megabytes.
public static int TotalPhysicalMemoryMB
{
get
{
try
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
if (GetPhysicallyInstalledSystemMemory(out var kb))
return (int)(kb / 1024);
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
// Read MemTotal from /proc/meminfo
foreach (var line in File.ReadAllLines("/proc/meminfo"))
{
if (line.StartsWith("MemTotal:", StringComparison.Ordinal))
{
var parts = line.Split(' ', StringSplitOptions.RemoveEmptyEntries);
if (parts.Length >= 2 && long.TryParse(parts[1], out var memKb))
return (int)(memKb / 1024);
}
}
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
// GC heap-size hint; not perfect but a reasonable fallback for macOS.
var gcInfo = GC.GetGCMemoryInfo();
if (gcInfo.TotalAvailableMemoryBytes > 0)
return (int)(gcInfo.TotalAvailableMemoryBytes / (1024 * 1024));
}
}
catch
{
// Fall through to default
}
return (int)(DefaultFallbackKB / 1024);
}
}
/// Recommended max user-allocatable RAM (leaves headroom for OS + other apps).
public static int SafeMaxAllocationMB
{
get
{
var total = TotalPhysicalMemoryMB;
// Leave at least 4 GB for OS + browser + Discord + everything else.
var headroom = total >= 32 * 1024 ? 6 * 1024 : 4 * 1024;
return Math.Max(2048, total - headroom);
}
}
}