From f1ffcad0a4daa35a955f9a382ac5d199aba9b1af Mon Sep 17 00:00:00 2001
From: Rye Mutt <rye@alchemyviewer.org>
Date: Fri, 13 Mar 2020 18:54:50 -0400
Subject: [PATCH] Make memory stats more accurate to actual system state on
 win64 and darwin

---
 indra/llcommon/llmemory.cpp | 62 ++++++++++++++++++++++++++++++-------
 1 file changed, 51 insertions(+), 11 deletions(-)

diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp
index 1884d6f04fb..32dfc858537 100644
--- a/indra/llcommon/llmemory.cpp
+++ b/indra/llcommon/llmemory.cpp
@@ -85,12 +85,13 @@ void LLMemory::initMaxHeapSizeGB(F32Gigabytes max_heap_size, BOOL prevent_heap_f
 void LLMemory::updateMemoryInfo() 
 {
 #if LL_WINDOWS
-	PROCESS_MEMORY_COUNTERS counters;
+	PROCESS_MEMORY_COUNTERS_EX counters;
+	counters.cb = sizeof(counters);
 
-	if (!GetProcessMemoryInfo(GetCurrentProcess(), &counters, sizeof(counters)))
+	if (!GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS*) &counters, sizeof(counters)))
 	{
 		LL_WARNS() << "GetProcessMemoryInfo failed" << LL_ENDL;
-		return ;
+		return;
 	}
 
 	sAllocatedMemInKB = U32Kilobytes::convert(U64Bytes(counters.WorkingSetSize));
@@ -98,26 +99,65 @@ void LLMemory::updateMemoryInfo()
 	sAllocatedPageSizeInKB = U32Kilobytes::convert(U64Bytes(counters.PagefileUsage));
 	sample(sVirtualMem, sAllocatedPageSizeInKB);
 
-	U32Kilobytes avail_phys, avail_virtual;
-	LLMemoryInfo::getAvailableMemoryKB(avail_phys, avail_virtual) ;
-	sMaxPhysicalMemInKB = llmin(avail_phys + sAllocatedMemInKB, sMaxHeapSizeInKB);
-
-	if(sMaxPhysicalMemInKB > sAllocatedMemInKB)
+	MEMORYSTATUSEX memorystat;
+	memorystat.dwLength = sizeof(memorystat);
+	if (!GlobalMemoryStatusEx(&memorystat))
 	{
-		sAvailPhysicalMemInKB = sMaxPhysicalMemInKB - sAllocatedMemInKB ;
+		LL_WARNS() << "GlobalMemoryStatusEx failed" << LL_ENDL;
+		return;
+	}
+#if (ADDRESS_SIZE==64)
+	sMaxPhysicalMemInKB = U32Kilobytes::convert(U64Bytes(memorystat.ullTotalPhys));
+	sAvailPhysicalMemInKB = U32Kilobytes::convert(U64Bytes(memorystat.ullAvailPhys));
+#else
+	sMaxPhysicalMemInKB = llmin(U32Kilobytes::convert(U64Bytes(memorystat.ullTotalPhys)), sMaxHeapSizeInKB);
+	if (sMaxPhysicalMemInKB > sAllocatedMemInKB)
+	{
+		sAvailPhysicalMemInKB = U32Kilobytes::convert(U64Bytes(memorystat.ullAvailPhys));
 	}
 	else
 	{
 		sAvailPhysicalMemInKB = U32Kilobytes(0);
 	}
+#endif
+
+#elif LL_DARWIN
+    mach_task_basic_info_data_t basicInfo;
+    mach_msg_type_number_t  basicInfoCount = MACH_TASK_BASIC_INFO_COUNT;
+    if (task_info(mach_task_self(), MACH_TASK_BASIC_INFO, (task_info_t)&basicInfo, &basicInfoCount) == KERN_SUCCESS)
+    {
+        sAllocatedMemInKB = U64Bytes(basicInfo.resident_size);
+        sample(sAllocatedMem, sAllocatedMemInKB);
+        sAllocatedPageSizeInKB = U64Bytes(basicInfo.virtual_size);
+        sample(sVirtualMem, sAllocatedPageSizeInKB);
+    }
+    
+    vm_size_t page_size;
+    vm_statistics64_data_t vm_stats;
+    mach_port_t mach_port = mach_host_self();
+    mach_msg_type_number_t count = HOST_VM_INFO64_COUNT;
+
+    if (KERN_SUCCESS == host_page_size(mach_port, &page_size) &&
+        KERN_SUCCESS == host_statistics64(mach_port, HOST_VM_INFO64,
+                                        (host_info64_t)&vm_stats, &count)) {
+        U64 total_memory = (vm_stats.free_count + 
+                            vm_stats.active_count +
+                            vm_stats.inactive_count + 
+                            vm_stats.wire_count +
+                            vm_stats.compressor_page_count) *  page_size;
+        sMaxPhysicalMemInKB = U64Bytes(total_memory);
+        sAvailPhysicalMemInKB = U64Bytes((vm_stats.free_count + vm_stats.inactive_count) * page_size);
+    } else {
+        sMaxPhysicalMemInKB = U64Bytes(U32_MAX);
+        sAvailPhysicalMemInKB = U64Bytes(U32_MAX);
+    }
+    
 #else
 	//not valid for other systems for now.
 	sAllocatedMemInKB = U64Bytes(LLMemory::getCurrentRSS());
 	sMaxPhysicalMemInKB = U64Bytes(U32_MAX);
 	sAvailPhysicalMemInKB = U64Bytes(U32_MAX);
 #endif
-
-	return ;
 }
 
 //
-- 
GitLab