From d9f0239755c361785295d2379a7e2e13412b951b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C8=86=E2=9C=A0Sa=CD=A5b=CD=A3e=CD=ABr=F0=9F=91=91?= =?UTF-8?q?=E2=B0=80?= Date: Tue, 26 Aug 2025 19:03:09 +0800 Subject: [PATCH 1/5] Fixes memory stats on macOS --- .../MemoryUtilization_Mac.tpp | 24 +++++++------------ 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/Common/Cpp/MemoryUtilization/MemoryUtilization_Mac.tpp b/Common/Cpp/MemoryUtilization/MemoryUtilization_Mac.tpp index 7ba6980721..95e5692090 100644 --- a/Common/Cpp/MemoryUtilization/MemoryUtilization_Mac.tpp +++ b/Common/Cpp/MemoryUtilization/MemoryUtilization_Mac.tpp @@ -94,6 +94,7 @@ MemoryUsage process_memory_usage(){ std::cerr << "Error getting process info for PID " << pid << ": " << strerror(errno) << std::endl; }else{ usage.process_physical_memory = task_info.pti_resident_size; + usage.process_virtual_memory = task_info.pti_virtual_size; } int mib[] = {CTL_HW, HW_MEMSIZE}; @@ -106,25 +107,16 @@ MemoryUsage process_memory_usage(){ usage.total_system_memory = physical_memory; } - vm_size_t page_size; vm_statistics_data_t vm_stats; - mach_port_t mach_port = mach_host_self(); - mach_msg_type_number_t count = sizeof(vm_stats) / sizeof(integer_t); - - // Get the host statistics - if (KERN_SUCCESS != host_statistics(mach_port, HOST_VM_INFO, (host_info_t)&vm_stats, &count)) { + mach_msg_type_number_t count = HOST_VM_INFO_COUNT; + if (host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)&vm_stats, &count) != 0) { std::cerr << "Failed to get host statistics." << std::endl; - } else{ - // Get the system's page size - host_page_size(mach_port, &page_size); - + } else { // Calculate used memory from vm_statistics - // Used memory = Wired + Active + Inactive - size_t wired_pages = vm_stats.wire_count; - size_t active_pages = vm_stats.active_count; - size_t inactive_pages = vm_stats.inactive_count; - - usage.total_used_system_memory = (wired_pages + active_pages + inactive_pages) * page_size; + // Used = active_count + wire_count + // Cached = inactive_count + // Buffered = purgeable_count + usage.total_used_system_memory = (size_t)(vm_stats.active_count + vm_stats.wire_count) * (size_t)vm_page_size; } return usage; } From 94132685c4aa5ae6aae2071b51bdae8608f33ece Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C8=86=E2=9C=A0Sa=CD=A5b=CD=A3e=CD=ABr=F0=9F=91=91?= =?UTF-8?q?=E2=B0=80?= Date: Wed, 27 Aug 2025 10:44:04 +0800 Subject: [PATCH 2/5] use task_info - get rid of libproc - in case we use task_vm_info_data_t.phys_footprint or those ledgers --- .../MemoryUtilization_Mac.tpp | 64 +++++++++---------- 1 file changed, 31 insertions(+), 33 deletions(-) diff --git a/Common/Cpp/MemoryUtilization/MemoryUtilization_Mac.tpp b/Common/Cpp/MemoryUtilization/MemoryUtilization_Mac.tpp index 95e5692090..eb1ea30b73 100644 --- a/Common/Cpp/MemoryUtilization/MemoryUtilization_Mac.tpp +++ b/Common/Cpp/MemoryUtilization/MemoryUtilization_Mac.tpp @@ -8,14 +8,12 @@ #define PokemonAutomation_MemoryUtilization_Mac_TPP #include -#include // For getpid() #include #include -#include -#include #include #include #include +#include #include namespace PokemonAutomation{ @@ -85,38 +83,38 @@ void analyze_vm_regions() { MemoryUsage process_memory_usage(){ MemoryUsage usage; - - pid_t pid = getpid(); - struct proc_taskinfo task_info; - int ret = proc_pidinfo(pid, PROC_PIDTASKINFO, 0, &task_info, sizeof(task_info)); - - if (ret <= 0) { - std::cerr << "Error getting process info for PID " << pid << ": " << strerror(errno) << std::endl; - }else{ - usage.process_physical_memory = task_info.pti_resident_size; - usage.process_virtual_memory = task_info.pti_virtual_size; + static int64_t physical_memory = 0; + if (physical_memory == 0) { + int mib[] = {CTL_HW, HW_MEMSIZE}; + size_t length = sizeof(physical_memory); + if (sysctl(mib, 2, &physical_memory, &length, NULL, 0) != 0) { + std::cerr << "Error calling sysctl()." << std::endl; + } } - - int mib[] = {CTL_HW, HW_MEMSIZE}; - int64_t physical_memory = 0; - size_t length = sizeof(physical_memory); - - if (sysctl(mib, 2, &physical_memory, &length, NULL, 0) != 0) { - std::cerr << "Error calling sysctl()." << std::endl; - } else{ - usage.total_system_memory = physical_memory; + usage.total_system_memory = physical_memory; + { + task_vm_info_data_t tvi; + mach_msg_type_number_t count = TASK_VM_INFO_COUNT; + if(KERN_SUCCESS == task_info(mach_task_self(), TASK_VM_INFO, (task_info_t) &tvi, &count)) + { + usage.process_physical_memory = tvi.resident_size; // resident_size = internal + external + reusable + usage.process_virtual_memory = tvi.virtual_size; + } else { + std::cerr << "Failed to get task info." << std::endl; + } } - - vm_statistics_data_t vm_stats; - mach_msg_type_number_t count = HOST_VM_INFO_COUNT; - if (host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)&vm_stats, &count) != 0) { - std::cerr << "Failed to get host statistics." << std::endl; - } else { - // Calculate used memory from vm_statistics - // Used = active_count + wire_count - // Cached = inactive_count - // Buffered = purgeable_count - usage.total_used_system_memory = (size_t)(vm_stats.active_count + vm_stats.wire_count) * (size_t)vm_page_size; + { + vm_statistics_data_t vm_stats; + mach_msg_type_number_t count = HOST_VM_INFO_COUNT; + if (KERN_SUCCESS == host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)&vm_stats, &count)) { + // Calculate used memory from vm_statistics + // Used = active_count + wire_count + // Cached = inactive_count + // Buffered = purgeable_count + usage.total_used_system_memory = (size_t)(vm_stats.active_count + vm_stats.wire_count) * (size_t)vm_page_size; + } else { + std::cerr << "Failed to get host statistics." << std::endl; + } } return usage; } From c90da2eb5290307c2dfeb69b708acc69cab1f1f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C8=86=E2=9C=A0Sa=CD=A5b=CD=A3e=CD=ABr=F0=9F=91=91?= =?UTF-8?q?=E2=B0=80?= Date: Wed, 27 Aug 2025 22:29:43 +0800 Subject: [PATCH 3/5] use mach_vm_region() to scan for process resident/swapped pages --- .../MemoryUtilization_Mac.tpp | 35 ++++++++++++++----- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/Common/Cpp/MemoryUtilization/MemoryUtilization_Mac.tpp b/Common/Cpp/MemoryUtilization/MemoryUtilization_Mac.tpp index eb1ea30b73..1707f68e57 100644 --- a/Common/Cpp/MemoryUtilization/MemoryUtilization_Mac.tpp +++ b/Common/Cpp/MemoryUtilization/MemoryUtilization_Mac.tpp @@ -13,9 +13,10 @@ #include #include #include -#include #include +#include "MemoryUtilization.h" + namespace PokemonAutomation{ @@ -93,15 +94,31 @@ MemoryUsage process_memory_usage(){ } usage.total_system_memory = physical_memory; { - task_vm_info_data_t tvi; - mach_msg_type_number_t count = TASK_VM_INFO_COUNT; - if(KERN_SUCCESS == task_info(mach_task_self(), TASK_VM_INFO, (task_info_t) &tvi, &count)) - { - usage.process_physical_memory = tvi.resident_size; // resident_size = internal + external + reusable - usage.process_virtual_memory = tvi.virtual_size; - } else { - std::cerr << "Failed to get task info." << std::endl; + mach_vm_address_t address = 0; + mach_vm_size_t size = 0; + vm_region_extended_info_data_t info; + mach_msg_type_number_t count = VM_REGION_EXTENDED_INFO_COUNT; + mach_port_t object_name; + unsigned int pages_resident = 0; + unsigned int pages_swapped_out = 0; + unsigned int pages_dirtied = 0; + + while (true) { + auto kr = mach_vm_region(mach_task_self(), &address, &size, VM_REGION_EXTENDED_INFO, (vm_region_info_t)&info, &count, &object_name); + if (kr != KERN_SUCCESS) { + if (kr == KERN_INVALID_ADDRESS) { // end of the address space + break; + } + std::cerr << "mach_vm_region_recurse failed with error: " << mach_error_string(kr) << std::endl; + break; + } + pages_resident += info.pages_resident; + pages_swapped_out += info.pages_swapped_out; + pages_dirtied += info.pages_dirtied; + address += size; } + usage.process_physical_memory = (size_t)(pages_resident - pages_dirtied) * (size_t)vm_page_size; + usage.process_virtual_memory = usage.process_physical_memory + (size_t)pages_swapped_out * (size_t)vm_page_size; } { vm_statistics_data_t vm_stats; From 7d74c9f263b075aff27db8a12ee2af1735a7a23c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C8=86=E2=9C=A0Sa=CD=A5b=CD=A3e=CD=ABr=F0=9F=91=91?= =?UTF-8?q?=E2=B0=80?= Date: Fri, 29 Aug 2025 23:00:13 +0800 Subject: [PATCH 4/5] Fixes total_used_system_memory --- .../MemoryUtilization_Mac.tpp | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/Common/Cpp/MemoryUtilization/MemoryUtilization_Mac.tpp b/Common/Cpp/MemoryUtilization/MemoryUtilization_Mac.tpp index 1707f68e57..e055ceade4 100644 --- a/Common/Cpp/MemoryUtilization/MemoryUtilization_Mac.tpp +++ b/Common/Cpp/MemoryUtilization/MemoryUtilization_Mac.tpp @@ -120,19 +120,31 @@ MemoryUsage process_memory_usage(){ usage.process_physical_memory = (size_t)(pages_resident - pages_dirtied) * (size_t)vm_page_size; usage.process_virtual_memory = usage.process_physical_memory + (size_t)pages_swapped_out * (size_t)vm_page_size; } + // ref: https://github.com/htop-dev/htop/blob/main/darwin/Platform.c + #ifdef __arm64__ + { + vm_statistics64_data_t vm_stats; + mach_msg_type_number_t count = HOST_VM_INFO64_COUNT; + if (KERN_SUCCESS == host_statistics64(mach_host_self(), HOST_VM_INFO64, (host_info_t)&vm_stats, &count)) { + auto used = vm_stats.active_count + vm_stats.inactive_count + + vm_stats.speculative_count + vm_stats.wire_count + vm_stats.compressor_page_count + - vm_stats.purgeable_count - vm_stats.external_page_count; + usage.total_used_system_memory = (size_t)used * (size_t)vm_page_size; + } else { + std::cerr << "Failed to get host statistics64." << std::endl; + } + } + #else { vm_statistics_data_t vm_stats; mach_msg_type_number_t count = HOST_VM_INFO_COUNT; if (KERN_SUCCESS == host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)&vm_stats, &count)) { - // Calculate used memory from vm_statistics - // Used = active_count + wire_count - // Cached = inactive_count - // Buffered = purgeable_count usage.total_used_system_memory = (size_t)(vm_stats.active_count + vm_stats.wire_count) * (size_t)vm_page_size; } else { std::cerr << "Failed to get host statistics." << std::endl; } } + #endif return usage; } From a21051ed8f7389a5776694405e7f01585b5ac22c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C8=86=E2=9C=A0Sa=CD=A5b=CD=A3e=CD=ABr=F0=9F=91=91?= =?UTF-8?q?=E2=B0=80?= Date: Sun, 31 Aug 2025 10:13:02 +0800 Subject: [PATCH 5/5] revert to use task_info for process used memory --- .../MemoryUtilization_Mac.tpp | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/Common/Cpp/MemoryUtilization/MemoryUtilization_Mac.tpp b/Common/Cpp/MemoryUtilization/MemoryUtilization_Mac.tpp index e055ceade4..58713ade45 100644 --- a/Common/Cpp/MemoryUtilization/MemoryUtilization_Mac.tpp +++ b/Common/Cpp/MemoryUtilization/MemoryUtilization_Mac.tpp @@ -94,30 +94,34 @@ MemoryUsage process_memory_usage(){ } usage.total_system_memory = physical_memory; { - mach_vm_address_t address = 0; + task_vm_info_data_t tvi; + mach_msg_type_number_t count = TASK_VM_INFO_COUNT; + if(KERN_SUCCESS == task_info(mach_task_self(), TASK_VM_INFO, (task_info_t) &tvi, &count)) + { + usage.process_physical_memory = tvi.resident_size; // resident_size = internal + external + reusable + } else { + std::cerr << "Failed to get task info." << std::endl; + } + } + { mach_vm_size_t size = 0; vm_region_extended_info_data_t info; mach_msg_type_number_t count = VM_REGION_EXTENDED_INFO_COUNT; mach_port_t object_name; - unsigned int pages_resident = 0; unsigned int pages_swapped_out = 0; - unsigned int pages_dirtied = 0; - while (true) { + for (mach_vm_address_t address = 0;; address += size) { auto kr = mach_vm_region(mach_task_self(), &address, &size, VM_REGION_EXTENDED_INFO, (vm_region_info_t)&info, &count, &object_name); if (kr != KERN_SUCCESS) { if (kr == KERN_INVALID_ADDRESS) { // end of the address space break; } - std::cerr << "mach_vm_region_recurse failed with error: " << mach_error_string(kr) << std::endl; + std::cerr << "mach_vm_region failed with error: " << mach_error_string(kr) << std::endl; break; } - pages_resident += info.pages_resident; pages_swapped_out += info.pages_swapped_out; - pages_dirtied += info.pages_dirtied; address += size; } - usage.process_physical_memory = (size_t)(pages_resident - pages_dirtied) * (size_t)vm_page_size; usage.process_virtual_memory = usage.process_physical_memory + (size_t)pages_swapped_out * (size_t)vm_page_size; } // ref: https://github.com/htop-dev/htop/blob/main/darwin/Platform.c