|
8 | 8 | #define PokemonAutomation_MemoryUtilization_Mac_TPP |
9 | 9 |
|
10 | 10 | #include <iostream> |
11 | | -#include <unistd.h> // For getpid() |
12 | 11 | #include <sys/types.h> |
13 | 12 | #include <sys/sysctl.h> |
14 | | -#include <sys/proc_info.h> |
15 | | -#include <libproc.h> |
16 | 13 | #include <mach/mach.h> |
17 | 14 | #include <mach/mach_host.h> |
18 | 15 | #include <mach/mach_vm.h> |
19 | 16 | #include <mach/vm_statistics.h> |
20 | 17 |
|
| 18 | +#include "MemoryUtilization.h" |
| 19 | + |
21 | 20 | namespace PokemonAutomation{ |
22 | 21 |
|
23 | 22 |
|
@@ -85,47 +84,71 @@ void analyze_vm_regions() { |
85 | 84 |
|
86 | 85 | MemoryUsage process_memory_usage(){ |
87 | 86 | MemoryUsage usage; |
88 | | - |
89 | | - pid_t pid = getpid(); |
90 | | - struct proc_taskinfo task_info; |
91 | | - int ret = proc_pidinfo(pid, PROC_PIDTASKINFO, 0, &task_info, sizeof(task_info)); |
92 | | - |
93 | | - if (ret <= 0) { |
94 | | - std::cerr << "Error getting process info for PID " << pid << ": " << strerror(errno) << std::endl; |
95 | | - }else{ |
96 | | - usage.process_physical_memory = task_info.pti_resident_size; |
| 87 | + static int64_t physical_memory = 0; |
| 88 | + if (physical_memory == 0) { |
| 89 | + int mib[] = {CTL_HW, HW_MEMSIZE}; |
| 90 | + size_t length = sizeof(physical_memory); |
| 91 | + if (sysctl(mib, 2, &physical_memory, &length, NULL, 0) != 0) { |
| 92 | + std::cerr << "Error calling sysctl()." << std::endl; |
| 93 | + } |
97 | 94 | } |
98 | | - |
99 | | - int mib[] = {CTL_HW, HW_MEMSIZE}; |
100 | | - int64_t physical_memory = 0; |
101 | | - size_t length = sizeof(physical_memory); |
102 | | - |
103 | | - if (sysctl(mib, 2, &physical_memory, &length, NULL, 0) != 0) { |
104 | | - std::cerr << "Error calling sysctl()." << std::endl; |
105 | | - } else{ |
106 | | - usage.total_system_memory = physical_memory; |
| 95 | + usage.total_system_memory = physical_memory; |
| 96 | + { |
| 97 | + task_vm_info_data_t tvi; |
| 98 | + mach_msg_type_number_t count = TASK_VM_INFO_COUNT; |
| 99 | + if(KERN_SUCCESS == task_info(mach_task_self(), TASK_VM_INFO, (task_info_t) &tvi, &count)) |
| 100 | + { |
| 101 | + usage.process_physical_memory = tvi.resident_size; // resident_size = internal + external + reusable |
| 102 | + } else { |
| 103 | + std::cerr << "Failed to get task info." << std::endl; |
| 104 | + } |
107 | 105 | } |
108 | | - |
109 | | - vm_size_t page_size; |
110 | | - vm_statistics_data_t vm_stats; |
111 | | - mach_port_t mach_port = mach_host_self(); |
112 | | - mach_msg_type_number_t count = sizeof(vm_stats) / sizeof(integer_t); |
113 | | - |
114 | | - // Get the host statistics |
115 | | - if (KERN_SUCCESS != host_statistics(mach_port, HOST_VM_INFO, (host_info_t)&vm_stats, &count)) { |
116 | | - std::cerr << "Failed to get host statistics." << std::endl; |
117 | | - } else{ |
118 | | - // Get the system's page size |
119 | | - host_page_size(mach_port, &page_size); |
120 | | - |
121 | | - // Calculate used memory from vm_statistics |
122 | | - // Used memory = Wired + Active + Inactive |
123 | | - size_t wired_pages = vm_stats.wire_count; |
124 | | - size_t active_pages = vm_stats.active_count; |
125 | | - size_t inactive_pages = vm_stats.inactive_count; |
126 | | - |
127 | | - usage.total_used_system_memory = (wired_pages + active_pages + inactive_pages) * page_size; |
| 106 | + { |
| 107 | + mach_vm_size_t size = 0; |
| 108 | + vm_region_extended_info_data_t info; |
| 109 | + mach_msg_type_number_t count = VM_REGION_EXTENDED_INFO_COUNT; |
| 110 | + mach_port_t object_name; |
| 111 | + unsigned int pages_swapped_out = 0; |
| 112 | + |
| 113 | + for (mach_vm_address_t address = 0;; address += size) { |
| 114 | + auto kr = mach_vm_region(mach_task_self(), &address, &size, VM_REGION_EXTENDED_INFO, (vm_region_info_t)&info, &count, &object_name); |
| 115 | + if (kr != KERN_SUCCESS) { |
| 116 | + if (kr == KERN_INVALID_ADDRESS) { // end of the address space |
| 117 | + break; |
| 118 | + } |
| 119 | + std::cerr << "mach_vm_region failed with error: " << mach_error_string(kr) << std::endl; |
| 120 | + break; |
| 121 | + } |
| 122 | + pages_swapped_out += info.pages_swapped_out; |
| 123 | + address += size; |
| 124 | + } |
| 125 | + usage.process_virtual_memory = usage.process_physical_memory + (size_t)pages_swapped_out * (size_t)vm_page_size; |
| 126 | + } |
| 127 | + // ref: https://github.com/htop-dev/htop/blob/main/darwin/Platform.c |
| 128 | + #ifdef __arm64__ |
| 129 | + { |
| 130 | + vm_statistics64_data_t vm_stats; |
| 131 | + mach_msg_type_number_t count = HOST_VM_INFO64_COUNT; |
| 132 | + if (KERN_SUCCESS == host_statistics64(mach_host_self(), HOST_VM_INFO64, (host_info_t)&vm_stats, &count)) { |
| 133 | + auto used = vm_stats.active_count + vm_stats.inactive_count + |
| 134 | + vm_stats.speculative_count + vm_stats.wire_count + vm_stats.compressor_page_count |
| 135 | + - vm_stats.purgeable_count - vm_stats.external_page_count; |
| 136 | + usage.total_used_system_memory = (size_t)used * (size_t)vm_page_size; |
| 137 | + } else { |
| 138 | + std::cerr << "Failed to get host statistics64." << std::endl; |
| 139 | + } |
| 140 | + } |
| 141 | + #else |
| 142 | + { |
| 143 | + vm_statistics_data_t vm_stats; |
| 144 | + mach_msg_type_number_t count = HOST_VM_INFO_COUNT; |
| 145 | + if (KERN_SUCCESS == host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)&vm_stats, &count)) { |
| 146 | + usage.total_used_system_memory = (size_t)(vm_stats.active_count + vm_stats.wire_count) * (size_t)vm_page_size; |
| 147 | + } else { |
| 148 | + std::cerr << "Failed to get host statistics." << std::endl; |
| 149 | + } |
128 | 150 | } |
| 151 | + #endif |
129 | 152 | return usage; |
130 | 153 | } |
131 | 154 |
|
|
0 commit comments