Unravel Engine C++ Reference
Loading...
Searching...
No Matches
process_memory.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "config.hpp"
4
5#include <cstdint>
6
7// Resident (physical) RAM for the current process — one lightweight query per call.
8// Intended for periodic sampling (e.g. profiler snapshots); cost is typically microseconds.
9
10#if UNRAVEL_PLATFORM_WINDOWS && (UNRAVEL_COMPILER_MSVC || UNRAVEL_COMPILER_CLANG)
11#define WIN32_LEAN_AND_MEAN
12#include <Windows.h>
13#include <Psapi.h>
14
15namespace platform
16{
17
18inline auto get_process_resident_set_bytes() -> int64_t
19{
20 PROCESS_MEMORY_COUNTERS pmc{};
21 pmc.cb = sizeof(pmc);
22 if(GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc)))
23 {
24 return static_cast<int64_t>(pmc.WorkingSetSize);
25 }
26 return 0;
27}
28
29inline auto get_system_physical_memory_bytes() -> int64_t
30{
31 MEMORYSTATUSEX status{};
32 status.dwLength = sizeof(status);
33 if(GlobalMemoryStatusEx(&status))
34 {
35 return static_cast<int64_t>(status.ullTotalPhys);
36 }
37 return 0;
38}
39
40inline auto get_system_available_physical_memory_bytes() -> int64_t
41{
42 MEMORYSTATUSEX status{};
43 status.dwLength = sizeof(status);
44 if(GlobalMemoryStatusEx(&status))
45 {
46 return static_cast<int64_t>(status.ullAvailPhys);
47 }
48 return 0;
49}
50
51inline auto get_system_used_physical_memory_bytes() -> int64_t
52{
53 const int64_t total = get_system_physical_memory_bytes();
54 const int64_t available = get_system_available_physical_memory_bytes();
55 if(total > 0 && available >= 0 && available <= total)
56 {
57 return total - available;
58 }
59 return 0;
60}
61
62} // namespace platform
63
64#elif UNRAVEL_PLATFORM_LINUX
65
66#include <cstdio>
67#include <unistd.h>
68
69namespace platform
70{
71
72inline auto get_process_resident_set_bytes() -> int64_t
73{
74 const long page_size = sysconf(_SC_PAGESIZE);
75 if(page_size <= 0)
76 {
77 return 0;
78 }
79 FILE* f = std::fopen("/proc/self/statm", "r");
80 if(f == nullptr)
81 {
82 return 0;
83 }
84 long long total_pages = 0;
85 long long resident_pages = 0;
86 const int n = std::fscanf(f, "%lld %lld", &total_pages, &resident_pages);
87 std::fclose(f);
88 if(n != 2)
89 {
90 return 0;
91 }
92 return static_cast<int64_t>(resident_pages * page_size);
93}
94
95inline auto get_system_physical_memory_bytes() -> int64_t
96{
97 const long page_size = sysconf(_SC_PAGESIZE);
98 const long num_pages = sysconf(_SC_PHYS_PAGES);
99 if(page_size > 0 && num_pages > 0)
100 {
101 return static_cast<int64_t>(page_size) * static_cast<int64_t>(num_pages);
102 }
103 return 0;
104}
105
106inline auto get_system_available_physical_memory_bytes() -> int64_t
107{
108 FILE* f = std::fopen("/proc/meminfo", "r");
109 if(f == nullptr)
110 {
111 return 0;
112 }
113
114 char line[256] = {};
115 long long mem_available_kb = -1;
116 while(std::fgets(line, sizeof(line), f) != nullptr)
117 {
118 if(std::sscanf(line, "MemAvailable: %lld kB", &mem_available_kb) == 1)
119 {
120 break;
121 }
122 }
123 std::fclose(f);
124
125 if(mem_available_kb < 0)
126 {
127 return 0;
128 }
129 return static_cast<int64_t>(mem_available_kb) * 1024;
130}
131
132inline auto get_system_used_physical_memory_bytes() -> int64_t
133{
134 const int64_t total = get_system_physical_memory_bytes();
135 const int64_t available = get_system_available_physical_memory_bytes();
136 if(total > 0 && available >= 0 && available <= total)
137 {
138 return total - available;
139 }
140 return 0;
141}
142
143} // namespace platform
144
145#elif UNRAVEL_PLATFORM_OSX
146
147#include <mach/mach.h>
148#include <mach/task_info.h>
149#include <sys/sysctl.h>
150
151namespace platform
152{
153
154inline auto get_process_resident_set_bytes() -> int64_t
155{
156 task_basic_info info{};
157 mach_msg_type_number_t count = TASK_BASIC_INFO_COUNT;
158 const kern_return_t kr =
159 task_info(mach_task_self(), TASK_BASIC_INFO, reinterpret_cast<task_info_t>(&info), &count);
160 if(kr != KERN_SUCCESS)
161 {
162 return 0;
163 }
164 return static_cast<int64_t>(info.resident_size);
165}
166
167inline auto get_system_physical_memory_bytes() -> int64_t
168{
169 int64_t mem = 0;
170 size_t len = sizeof(mem);
171 if(sysctlbyname("hw.memsize", &mem, &len, nullptr, 0) == 0)
172 {
173 return mem;
174 }
175 return 0;
176}
177
178inline auto get_system_available_physical_memory_bytes() -> int64_t
179{
180 vm_statistics64_data_t vm_stats{};
181 mach_msg_type_number_t count = HOST_VM_INFO64_COUNT;
182 const kern_return_t kr = host_statistics64(mach_host_self(),
183 HOST_VM_INFO64,
184 reinterpret_cast<host_info64_t>(&vm_stats),
185 &count);
186 if(kr != KERN_SUCCESS)
187 {
188 return 0;
189 }
190
191 const int64_t page_size = static_cast<int64_t>(vm_page_size);
192 const int64_t free_pages = static_cast<int64_t>(vm_stats.free_count) +
193 static_cast<int64_t>(vm_stats.inactive_count) +
194 static_cast<int64_t>(vm_stats.purgeable_count);
195 return free_pages * page_size;
196}
197
198inline auto get_system_used_physical_memory_bytes() -> int64_t
199{
200 const int64_t total = get_system_physical_memory_bytes();
201 const int64_t available = get_system_available_physical_memory_bytes();
202 if(total > 0 && available >= 0 && available <= total)
203 {
204 return total - available;
205 }
206 return 0;
207}
208
209} // namespace platform
210
211#else
212
213namespace platform
214{
215
216inline auto get_process_resident_set_bytes() -> int64_t
217{
218 return 0;
219}
220
221inline auto get_system_physical_memory_bytes() -> int64_t
222{
223 return 0;
224}
225
227{
228 return 0;
229}
230
232{
233 return 0;
234}
235
236} // namespace platform
237
238#endif
auto get_system_available_physical_memory_bytes() -> int64_t
auto get_system_used_physical_memory_bytes() -> int64_t
auto get_process_resident_set_bytes() -> int64_t
auto get_system_physical_memory_bytes() -> int64_t
uint32_t count