diff --git a/Common/Cpp/MemoryUtilization/MemoryUtilization_Mac.tpp b/Common/Cpp/MemoryUtilization/MemoryUtilization_Mac.tpp index 7ba6980721..58713ade45 100644 --- a/Common/Cpp/MemoryUtilization/MemoryUtilization_Mac.tpp +++ b/Common/Cpp/MemoryUtilization/MemoryUtilization_Mac.tpp @@ -8,16 +8,15 @@ #define PokemonAutomation_MemoryUtilization_Mac_TPP #include -#include // For getpid() #include #include -#include -#include #include #include #include #include +#include "MemoryUtilization.h" + namespace PokemonAutomation{ @@ -85,47 +84,71 @@ 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; + 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 + } else { + std::cerr << "Failed to get task info." << std::endl; + } } - - 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)) { - std::cerr << "Failed to get host statistics." << std::endl; - } else{ - // Get the system's page size - host_page_size(mach_port, &page_size); - - // 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; + { + 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_swapped_out = 0; + + 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 failed with error: " << mach_error_string(kr) << std::endl; + break; + } + pages_swapped_out += info.pages_swapped_out; + address += 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)) { + 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; }