From e07231ca394894e777085182795fb66045b48c9a Mon Sep 17 00:00:00 2001 From: Roger Luedecke Date: Tue, 15 Sep 2026 15:11:00 -0700 Subject: [PATCH] fix(linux): parse MemAvailable from /proc/meminfo instead of get_avphys_pages() On Linux, get_avphys_pages() maps to sysconf(_SC_AVPHYS_PAGES) which returns only completely unallocated pages (MemFree). The Linux kernel eagerly uses spare physical RAM for disk caching (buff/cache). When active disk caching fills memory, MemFree routinely hovers between 200-500 MB even when gigabytes of memory are available. This caused the viewer's memory budget logic to falsely report low system memory (<256 MB), repeatedly triggering emergency texture downrezzing loops and dynamic draw-distance halving. Replace get_avphys_pages() in LLMemoryInfo::updateAvailableMemory() with a fast, non-allocating single fread of MemAvailable: from /proc/meminfo (available on Linux >= 3.14), with fallback to get_avphys_pages(). --- indra/llcommon/llsys.cpp | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp index a1ae290267..f489110755 100644 --- a/indra/llcommon/llsys.cpp +++ b/indra/llcommon/llsys.cpp @@ -851,8 +851,33 @@ void LLMemoryInfo::updateAvailableMemory() } #elif LL_LINUX - U64 phys = U64(getpagesize()) * U64(get_avphys_pages()); - LLMemory::sAvailPhysicalMemInKB = U64Bytes(phys); + bool found_available = false; + LLFILE* fp = LLFile::fopen(MEMINFO_FILE, LLFILE_MODE("rb")); + if (fp) + { + char buff[2048]; + size_t nbytes = fread(buff, 1, sizeof(buff) - 1, fp); + buff[nbytes] = '\0'; + fclose(fp); + + char* memp = strstr(buff, "MemAvailable:"); + if (memp) + { + unsigned long long mem_avail_kb = 0; + if (sscanf(memp, "MemAvailable: %llu", &mem_avail_kb) == 1) + { + LLMemory::sAvailPhysicalMemInKB = U32Kilobytes(mem_avail_kb); + found_available = true; + } + } + } + + if (!found_available) + { + // Fallback for pre-3.14 kernels or container environments without MemAvailable + U64 phys = U64(getpagesize()) * U64(get_avphys_pages()); + LLMemory::sAvailPhysicalMemInKB = U64Bytes(phys); + } #else //do not know how to collect available memory info for other systems. //leave it blank here for now.