Skip to content

Commit da10407

Browse files
committed
Add memory to stats. Add Windows and partial Linux implementations.
1 parent 807e05b commit da10407

15 files changed

+617
-155
lines changed
Lines changed: 14 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -1,144 +1,27 @@
1-
#include <iostream>
2-
3-
#if defined(__linux) || defined(__APPLE__)
4-
// get process phsyical memory for Linux and macOS
5-
#include <libproc.h>
6-
#include <sys/proc_info.h>
7-
#include <unistd.h> // For getpid()
8-
#endif
1+
/* Memory Utilization
2+
*
3+
* From: https://github.com/PokemonAutomation/
4+
*
5+
*/
96

10-
#if defined(__APPLE__)
11-
// get system memory and process virutal memory for macOS
12-
#include <sys/sysctl.h>
13-
#include <mach/mach_host.h>
14-
#include <mach/vm_statistics.h>
15-
#include <mach/mach.h>
16-
#include <mach/mach_vm.h>
17-
#include <sys/types.h>
18-
#endif
197

208
#include "MemoryUtilization.h"
219

22-
namespace PokemonAutomation{
23-
10+
#if 0
2411

12+
#elif _WIN32
13+
#include "MemoryUtilization_Windows.tpp"
2514

26-
/**
27-
* @brief Retrieves and analyzes the virtual memory regions of the current process.
28-
*/
29-
void analyze_vm_regions() {
30-
kern_return_t kr;
31-
mach_port_t task = mach_task_self();
32-
33-
mach_vm_address_t address = 0;
34-
mach_vm_size_t size = 0;
35-
36-
vm_region_basic_info_data_64_t info;
37-
mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT_64;
38-
39-
mach_port_t object_name;
40-
41-
// Total virtual memory usage
42-
mach_vm_size_t total_size = 0;
43-
44-
std::cout << "Analyzing virtual memory regions for current process..." << std::endl;
45-
46-
// Loop through all virtual memory regions
47-
while (true) {
48-
kr = mach_vm_region(task, &address, &size, VM_REGION_BASIC_INFO_64, (vm_region_info_t)&info, &info_count, &object_name);
49-
50-
if (kr == KERN_INVALID_ADDRESS) {
51-
// Reached the end of the address space
52-
break;
53-
} else if (kr != KERN_SUCCESS) {
54-
std::cerr << "mach_vm_region failed with error: " << kr << std::endl;
55-
break;
56-
}
15+
#elif __APPLE__
16+
#include "MemoryUtilization_Mac.tpp"
5717

58-
// Add region size to total
59-
total_size += size;
18+
#elif __linux
19+
#include "MemoryUtilization_Linux.tpp"
6020

61-
// Print details of the current region
62-
std::cout << "Region at address " << (void*)address
63-
<< ", size " << size << " bytes"
64-
<< ", protection: ";
65-
66-
if (info.protection & VM_PROT_READ) {
67-
std::cout << "R";
68-
}
69-
if (info.protection & VM_PROT_WRITE) {
70-
std::cout << "W";
71-
}
72-
if (info.protection & VM_PROT_EXECUTE) {
73-
std::cout << "X";
74-
}
75-
std::cout << std::endl;
76-
77-
// Move to the next region
78-
address += size;
21+
namespace PokemonAutomation{
22+
MemoryUsage process_memory_usage(){
7923
}
80-
81-
std::cout << "\nTotal virtual memory allocated: " << total_size << " bytes" << std::endl;
82-
std::cout << "Approximately " << (double)total_size / 1048576.0 << " MB" << std::endl;
8324
}
84-
85-
86-
MemoryUsage process_memory_usage(){
87-
MemoryUsage usage;
88-
89-
#if defined(__linux) || defined(__APPLE__)
90-
pid_t pid = getpid();
91-
struct proc_taskinfo task_info;
92-
int ret = proc_pidinfo(pid, PROC_PIDTASKINFO, 0, &task_info, sizeof(task_info));
93-
94-
if (ret <= 0) {
95-
std::cerr << "Error getting process info for PID " << pid << ": " << strerror(errno) << std::endl;
96-
}else{
97-
usage.process_physical_memory = task_info.pti_resident_size;
98-
}
99-
100-
#if defined(__APPLE__) // compute rest of the memory info on macOS
101-
102-
int mib[] = {CTL_HW, HW_MEMSIZE};
103-
int64_t physical_memory = 0;
104-
size_t length = sizeof(physical_memory);
105-
106-
if (sysctl(mib, 2, &physical_memory, &length, NULL, 0) != 0) {
107-
std::cerr << "Error calling sysctl()." << std::endl;
108-
} else{
109-
usage.total_system_memory = physical_memory;
110-
}
111-
112-
vm_size_t page_size;
113-
vm_statistics_data_t vm_stats;
114-
mach_port_t mach_port = mach_host_self();
115-
mach_msg_type_number_t count = sizeof(vm_stats) / sizeof(integer_t);
116-
117-
// Get the host statistics
118-
if (KERN_SUCCESS != host_statistics(mach_port, HOST_VM_INFO, (host_info_t)&vm_stats, &count)) {
119-
std::cerr << "Failed to get host statistics." << std::endl;
120-
} else{
121-
// Get the system's page size
122-
host_page_size(mach_port, &page_size);
123-
124-
// Calculate used memory from vm_statistics
125-
// Used memory = Wired + Active + Inactive
126-
size_t wired_pages = vm_stats.wire_count;
127-
size_t active_pages = vm_stats.active_count;
128-
size_t inactive_pages = vm_stats.inactive_count;
129-
130-
usage.total_used_system_memory = (wired_pages + active_pages + inactive_pages) * page_size;
131-
}
132-
133-
#else // compute total used system memory on Linux
134-
// TODO
13525
#endif
13626

137-
#else // compute memory info on Windows
138-
// TODO
139-
#endif
140-
return usage;
141-
}
142-
14327

144-
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/* Memory Utilization
2+
*
3+
* From: https://github.com/PokemonAutomation/
4+
*
5+
*/
6+
7+
#ifndef PokemonAutomation_MemoryUtilization_Linux_TPP
8+
#define PokemonAutomation_MemoryUtilization_Linux_TPP
9+
10+
#include <utility>
11+
#include <string>
12+
#include <fstream>
13+
#include <iostream>
14+
#include <unistd.h>
15+
#include <sys/proc_info.h>
16+
#include "MemoryUtilization.h"
17+
18+
namespace PokemonAutomation{
19+
20+
21+
22+
MemoryUsage process_memory_usage(){
23+
MemoryUsage usage;
24+
25+
26+
usage.total_system_memory = (uint64_t)sysconf(_SC_PHYS_PAGES) * sysconf(_SC_PAGE_SIZE);
27+
28+
{
29+
uint64_t bytes = 0;
30+
31+
const std::string TOKEN = "MemAvailable:";
32+
33+
std::ifstream file("/proc/meminfo");
34+
std::string line;
35+
while (std::getline(file, line)){
36+
size_t pos = line.find(TOKEN);
37+
if (pos == std::string::npos){
38+
continue;
39+
}
40+
41+
// Skip the token.
42+
pos += TOKEN.size();
43+
44+
// Skip the white space.
45+
while (line[pos] != '\0' && line[pos] == ' '){
46+
pos++;
47+
}
48+
49+
// Parse the integer.
50+
while (true){
51+
char ch = line[pos++];
52+
if (ch < '0' || ch > '9'){
53+
break;
54+
}
55+
bytes *= 10;
56+
bytes += ch - '0';
57+
}
58+
bytes *= 1024;
59+
60+
break;
61+
}
62+
63+
if (bytes == 0){
64+
bytes = (uint64_t)sysconf(_SC_AVPHYS_PAGES) * sysconf(_SC_PAGE_SIZE);
65+
}
66+
bytes = std::min(bytes, usage.total_system_memory);
67+
68+
usage.total_used_system_memory = usage.total_system_memory - bytes;
69+
}
70+
71+
pid_t pid = getpid();
72+
struct proc_taskinfo task_info;
73+
int ret = proc_pidinfo(pid, PROC_PIDTASKINFO, 0, &task_info, sizeof(task_info));
74+
75+
if (ret <= 0) {
76+
std::cerr << "Error getting process info for PID " << pid << ": " << strerror(errno) << std::endl;
77+
}else{
78+
usage.process_physical_memory = task_info.pti_resident_size;
79+
}
80+
81+
return usage;
82+
}
83+
84+
85+
86+
87+
}
88+
#endif
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
/* Memory Utilization
2+
*
3+
* From: https://github.com/PokemonAutomation/
4+
*
5+
*/
6+
7+
#ifndef PokemonAutomation_MemoryUtilization_Mac_TPP
8+
#define PokemonAutomation_MemoryUtilization_Mac_TPP
9+
10+
#include <iostream>
11+
#include <unistd.h> // For getpid()
12+
#include <sys/types.h>
13+
#include <sys/sysctl.h>
14+
#include <sys/proc_info.h>
15+
#include <libproc.h>
16+
#include <mach/mach.h>
17+
#include <mach/mach_host.h>
18+
#include <mach/mach_vm.h>
19+
#include <mach/vm_statistics.h>
20+
21+
namespace PokemonAutomation{
22+
23+
24+
25+
/**
26+
* @brief Retrieves and analyzes the virtual memory regions of the current process.
27+
*/
28+
void analyze_vm_regions() {
29+
kern_return_t kr;
30+
mach_port_t task = mach_task_self();
31+
32+
mach_vm_address_t address = 0;
33+
mach_vm_size_t size = 0;
34+
35+
vm_region_basic_info_data_64_t info;
36+
mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT_64;
37+
38+
mach_port_t object_name;
39+
40+
// Total virtual memory usage
41+
mach_vm_size_t total_size = 0;
42+
43+
std::cout << "Analyzing virtual memory regions for current process..." << std::endl;
44+
45+
// Loop through all virtual memory regions
46+
while (true) {
47+
kr = mach_vm_region(task, &address, &size, VM_REGION_BASIC_INFO_64, (vm_region_info_t)&info, &info_count, &object_name);
48+
49+
if (kr == KERN_INVALID_ADDRESS) {
50+
// Reached the end of the address space
51+
break;
52+
} else if (kr != KERN_SUCCESS) {
53+
std::cerr << "mach_vm_region failed with error: " << kr << std::endl;
54+
break;
55+
}
56+
57+
// Add region size to total
58+
total_size += size;
59+
60+
// Print details of the current region
61+
std::cout << "Region at address " << (void*)address
62+
<< ", size " << size << " bytes"
63+
<< ", protection: ";
64+
65+
if (info.protection & VM_PROT_READ) {
66+
std::cout << "R";
67+
}
68+
if (info.protection & VM_PROT_WRITE) {
69+
std::cout << "W";
70+
}
71+
if (info.protection & VM_PROT_EXECUTE) {
72+
std::cout << "X";
73+
}
74+
std::cout << std::endl;
75+
76+
// Move to the next region
77+
address += size;
78+
}
79+
80+
std::cout << "\nTotal virtual memory allocated: " << total_size << " bytes" << std::endl;
81+
std::cout << "Approximately " << (double)total_size / 1048576.0 << " MB" << std::endl;
82+
}
83+
84+
85+
86+
MemoryUsage process_memory_usage(){
87+
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;
97+
}
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;
107+
}
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;
128+
}
129+
return usage;
130+
}
131+
132+
133+
134+
135+
}
136+
#endif

0 commit comments

Comments
 (0)