From 003452fbbb5a55b2456b161d4464f60524c8f165 Mon Sep 17 00:00:00 2001 From: lightningterror <18107717+lightningterror@users.noreply.github.com> Date: Mon, 21 Apr 2025 11:03:01 +0200 Subject: [PATCH] common-linux: Try to read cached/buffered memory using MemAvailable. Add two fallbacks if MemAvailable isn't available: 1. Add manual approximation/Linux-like heuristic fallback. 2. Add sysinfo if manual approximation fails. --- common/Linux/LnxMisc.cpp | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/common/Linux/LnxMisc.cpp b/common/Linux/LnxMisc.cpp index 2ef073932b..bdba7d7aa3 100644 --- a/common/Linux/LnxMisc.cpp +++ b/common/Linux/LnxMisc.cpp @@ -43,11 +43,45 @@ u64 GetPhysicalMemory() u64 GetAvailablePhysicalMemory() { - struct sysinfo info; + // Try to read MemAvailable from /proc/meminfo. + FILE* file = fopen("/proc/meminfo", "r"); + if (file) + { + u64 mem_available = 0; + u64 mem_free = 0, buffers = 0, cached = 0, sreclaimable = 0, shmem = 0; + char line[256]; + + while (fgets(line, sizeof(line), file)) + { + // Modern kernels provide MemAvailable directly - preferred and most accurate. + if (sscanf(line, "MemAvailable: %llu kB", &mem_available) == 1) + { + fclose(file); + return mem_available * _1kb; + } + + // Fallback values for manual approximation. + sscanf(line, "MemFree: %llu kB", &mem_free); + sscanf(line, "Buffers: %llu kB", &buffers); + sscanf(line, "Cached: %llu kB", &cached); + sscanf(line, "SReclaimable: %llu kB", &sreclaimable); + sscanf(line, "Shmem: %llu kB", &shmem); + } + fclose(file); + + // Fallback approximation: Linux-like heuristic. + // available = MemFree + Buffers + Cached + SReclaimable - Shmem. + const u64 available_kb = mem_free + buffers + cached + sreclaimable - shmem; + return available_kb * _1kb; + } + + // Fallback to sysinfo if /proc/meminfo couldn't be read. + struct sysinfo info = {}; if (sysinfo(&info) != 0) return 0; - return static_cast(info.freeram) * info.mem_unit; + // Note: This does NOT include cached memory - only free + buffer. + return (static_cast(info.freeram) + static_cast(info.bufferram)) * static_cast(info.mem_unit); } u64 GetTickFrequency()