2 #ifndef ENIGMA_CPU_INFO_H
3 #define ENIGMA_CPU_INFO_H
9 #if defined(ENIGMA_PLATFORM_WINDOWS)
12 #elif defined(ENIGMA_PLATFORM_LINUX)
17 #include <sys/times.h>
18 #elif defined(ENIGMA_PLATFORM_MACOS)
20 #include <mach/mach_error.h>
21 #include <mach/mach_host.h>
22 #include <mach/mach_init.h>
23 #include <mach/vm_map.h>
51 #if defined(ENIGMA_PLATFORM_WINDOWS) || defined(ENIGMA_PLATFORM_MACOS)
55 float CalculateCPULoad(
const std::uint64_t idle_ticks,
const std::uint64_t total_ticks) {
56 const std::uint64_t total_ticks_since_last_time = total_ticks - m_cpu_previous_total_ticks;
57 const std::uint64_t idle_ticks_since_last_time = idle_ticks - m_cpu_previous_idle_ticks;
59 const float rate = 1.0f - ((total_ticks_since_last_time > 0) ?
static_cast<float>(idle_ticks_since_last_time) / total_ticks_since_last_time : 0.0f);
61 m_cpu_previous_total_ticks = total_ticks;
62 m_cpu_previous_idle_ticks = idle_ticks;
64 return (rate * 100.0f);
70 #if defined(ENIGMA_PLATFORM_WINDOWS)
72 FILETIME m_idle_time{}, m_kernel_time{}, m_user_time{};
73 std::uint64_t m_cpu_previous_total_ticks{0};
74 std::uint64_t m_cpu_previous_idle_ticks{0};
76 std::uint64_t FileTimeToUInt64(
const FILETIME& file_time) {
77 return (
static_cast<std::uint64_t
>(file_time.dwHighDateTime) << 32) |
static_cast<std::uint64_t
>(file_time.dwLowDateTime);
80 #elif defined(ENIGMA_PLATFORM_LINUX)
82 std::uint64_t m_last_total_user{0};
83 std::uint64_t m_last_total_user_low{0};
84 std::uint64_t m_last_total_sys{0};
85 std::uint64_t m_last_total_idle{0};
87 #elif defined(ENIGMA_PLATFORM_MACOS)
89 std::uint64_t m_cpu_previous_total_ticks{0};
90 std::uint64_t m_cpu_previous_idle_ticks{0};
91 host_cpu_load_info_data_t m_cpu_info{};
92 mach_msg_type_number_t m_count = HOST_CPU_LOAD_INFO_COUNT;
106 #ifndef ENIGMA_CPU_INFO_H
107 #define ENIGMA_CPU_INFO_H
109 #undef ENIGMA_PLATFORM_WINDOWS
110 #define ENIGMA_PLATFORM_LINUX 1
115 #if defined(ENIGMA_PLATFORM_WINDOWS)
118 #elif defined(ENIGMA_PLATFORM_LINUX)
121 #include <sys/times.h>
122 #include <sys/vtimes.h>
123 #elif defined(ENIGMA_PLATFORM_MACOS)
125 #include <mach/mach_error.h>
126 #include <mach/mach_host.h>
127 #include <mach/mach_init.h>
128 #include <mach/vm_map.h>
140 #if defined(ENIGMA_PLATFORM_WINDOWS)
141 ::SYSTEM_INFO sys_info{};
142 ::FILETIME ftime{}, fsys{}, fuser{};
144 ::GetSystemInfo(&sys_info);
145 m_num_processors = sys_info.dwNumberOfProcessors;
147 ::GetSystemTimeAsFileTime(&ftime);
148 std::memcpy(&m_last_cpu, &ftime,
sizeof(FILETIME));
150 ::GetProcessTimes(::GetCurrentProcess(), &ftime, &ftime, &fsys, &fuser);
151 std::memcpy(&m_last_sys_cpu, &fsys,
sizeof(FILETIME));
152 std::memcpy(&m_last_user_cpu, &fuser,
sizeof(FILETIME));
153 #elif defined(ENIGMA_PLATFORM_LINUX)
155 struct tms timeSample {};
158 lastCPU = times(&timeSample);
159 lastSysCPU = timeSample.tms_stime;
160 lastUserCPU = timeSample.tms_utime;
162 file = fopen(
"/proc/cpuinfo",
"r");
164 while (fgets(line, 128, file) != NULL) {
165 if (strncmp(line,
"processor", 9) == 0) numProcessors++;
183 float percentage{ 0.0f };
185 #if defined(ENIGMA_PLATFORM_WINDOWS)
187 if (::GetSystemTimes(&m_idle_time, &m_kernel_time, &m_user_time))
189 const std::uint64_t idle_ticks = this->FileTimeToUInt64(m_idle_time);
190 const std::uint64_t total_ticks = this->FileTimeToUInt64(m_kernel_time) + this->FileTimeToUInt64(m_user_time);
191 percentage = this->CalculateCPULoad(idle_ticks, total_ticks);
194 percentage = -100.0f;
196 #elif defined(ENIGMA_PLATFORM_LINUX)
198 std::uint64_t total_user{}, total_user_low{}, total_sys{}, total_idle{}, total{};
200 std::FILE* file = std::fopen(
"/proc/stat",
"r");
201 std::fscanf(file,
"cpu %llu %llu %llu %llu",
202 &total_user, &total_user_low,
203 &total_sys, &total_idle);
206 if (total_user < m_last_total_user || total_user_low < m_last_total_user_low ||
207 total_sys < m_last_total_sys || total_idle < m_last_total_idle)
210 percentage = -100.0f;
214 total = (total_user - m_last_total_user) + (total_user_low - m_last_total_user_low) + (total_sys - m_last_total_sys);
215 percentage =
static_cast<float>(total);
216 total += (total_idle - m_last_total_idle);
218 percentage *= 100.0f;
221 m_last_total_user = total_user;
222 m_last_total_user_low = total_user_low;
223 m_last_total_sys = total_sys;
224 m_last_total_idle = total_idle;
226 #elif defined(ENIGMA_PLATFORM_MACOS)
227 if (host_statistics(mach_host_self(), HOST_CPU_LOAD_INFO, (host_info_t)&m_cpu_info, &m_count) == KERN_SUCCESS)
229 std::uint64_t total_ticks{ 0 };
230 for (
auto i = 0; i < CPU_STATE_MAX; ++i)
231 total_ticks += m_cpu_info.cpu_ticks[i];
232 const std::uint64_t idle_ticks = m_cpu_info.cpu_ticks[CPU_STATE_IDLE];
233 percentage = this->CalculateCPULoad(idle_ticks, total_ticks);
236 percentage = -100.0f;
248 #if defined(ENIGMA_PLATFORM_WINDOWS)
250 ULARGE_INTEGER
now{}, sys{}, user{};
252 ::GetSystemTimeAsFileTime(&m_idle_time);
253 std::memcpy(&
now, &m_idle_time,
sizeof(FILETIME));
255 ::GetProcessTimes(::GetCurrentProcess(), &m_idle_time, &m_idle_time, &m_kernel_time, &m_user_time);
256 std::memcpy(&sys, &m_kernel_time,
sizeof(FILETIME));
257 std::memcpy(&user, &m_user_time,
sizeof(FILETIME));
259 float percent =
static_cast<float>(sys.QuadPart - m_last_sys_cpu.QuadPart) +
static_cast<float>(user.QuadPart - m_last_user_cpu.QuadPart);
260 percent /=
static_cast<float>(
now.QuadPart - m_last_cpu.QuadPart);
261 percent /=
static_cast<float>(m_num_processors);
264 m_last_user_cpu = user;
265 m_last_sys_cpu = sys;
267 return percent * 100.0f;
269 #elif defined(ENIGMA_PLATFORM_LINUX)
270 #elif defined(ENIGMA_PLATFORM_MACOS)
278 #if defined(ENIGMA_PLATFORM_WINDOWS) || defined(ENIGMA_PLATFORM_MACOS)
282 float CalculateCPULoad(
const std::uint64_t idle_ticks,
const std::uint64_t total_ticks)
284 const std::uint64_t total_ticks_since_last_time = total_ticks - m_cpu_previous_total_ticks;
285 const std::uint64_t idle_ticks_since_last_time = idle_ticks - m_cpu_previous_idle_ticks;
287 const float rate = 1.0f - ((total_ticks_since_last_time > 0) ?
static_cast<float>(idle_ticks_since_last_time) / total_ticks_since_last_time : 0.0f);
289 m_cpu_previous_total_ticks = total_ticks;
290 m_cpu_previous_idle_ticks = idle_ticks;
292 return (rate * 100.0f);
298 #if defined(ENIGMA_PLATFORM_WINDOWS)
300 FILETIME m_idle_time{}, m_kernel_time{}, m_user_time{};
301 ULARGE_INTEGER m_last_cpu{}, m_last_user_cpu{}, m_last_sys_cpu{};
302 std::int32_t m_num_processors{};
304 std::uint64_t m_cpu_previous_total_ticks{ 0 };
305 std::uint64_t m_cpu_previous_idle_ticks{ 0 };
307 std::uint64_t FileTimeToUInt64(
const FILETIME& file_time)
309 return (
static_cast<std::uint64_t
>(file_time.dwHighDateTime) << 32) |
static_cast<std::uint64_t
>(file_time.dwLowDateTime);
312 #elif defined(ENIGMA_PLATFORM_LINUX)
314 std::uint64_t m_last_total_user{ 0 };
315 std::uint64_t m_last_total_user_low{ 0 };
316 std::uint64_t m_last_total_sys{ 0 };
317 std::uint64_t m_last_total_idle{ 0 };
319 std::int32_t m_num_processors{};
321 #elif defined(ENIGMA_PLATFORM_MACOS)
323 std::uint64_t m_cpu_previous_total_ticks{ 0 };
324 std::uint64_t m_cpu_previous_idle_ticks{ 0 };
325 host_cpu_load_info_data_t m_cpu_info{};
326 mach_msg_type_number_t m_count = HOST_CPU_LOAD_INFO_COUNT;
#define NS_ENIGMA_BEGIN
Enable/Disable Assertions.
float GetProcessCPUUsage() noexcept
ENIGMA_NON_MOVEABLE(CPUInfo)
~CPUInfo() noexcept=default
ENIGMA_NON_COPYABLE(CPUInfo)
float GetCPUUsage() noexcept
static std::string now(const std::string_view &format="%Y-%m-%d %H:%M:%S")
returns current date and time as a string with a specific format