Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 64 additions & 41 deletions Common/Cpp/MemoryUtilization/MemoryUtilization_Mac.tpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,15 @@
#define PokemonAutomation_MemoryUtilization_Mac_TPP

#include <iostream>
#include <unistd.h> // For getpid()
#include <sys/types.h>
#include <sys/sysctl.h>
#include <sys/proc_info.h>
#include <libproc.h>
#include <mach/mach.h>
#include <mach/mach_host.h>
#include <mach/mach_vm.h>
#include <mach/vm_statistics.h>

#include "MemoryUtilization.h"

namespace PokemonAutomation{


Expand Down Expand Up @@ -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;
}

Expand Down