Enigma 3.2.2
A Simple, Reliable and Efficient Encryption Tool
Loading...
Searching...
No Matches
CPUInfo.hpp
Go to the documentation of this file.
1#pragma once
2#ifndef ENIGMA_CPU_INFO_H
3#define ENIGMA_CPU_INFO_H
4
5
6#include <Core/Core.hpp>
7#include <Logger/Logger.hpp>
8
9#if defined(ENIGMA_PLATFORM_WINDOWS)
10// Windows Includes
11#include <Windows.h>
12#elif defined(ENIGMA_PLATFORM_LINUX)
13// Linux Includes
14#include <cstdio>
15#include <cstdlib>
16#include <cstring>
17#include <sys/times.h>
18#elif defined(ENIGMA_PLATFORM_MACOS)
19// MacOS Includes
20#include <mach/mach_error.h>
21#include <mach/mach_host.h>
22#include <mach/mach_init.h>
23#include <mach/vm_map.h>
24#endif
25
30class CPUInfo {
31 public:
32 CPUInfo() noexcept;
33 ~CPUInfo() noexcept = default;
34
37
38
39 public:
43 float GetCPUUsage() noexcept;
44
48 float GetProcessCPUUsage() noexcept;
49
50 private:
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;
58
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);
60
61 m_cpu_previous_total_ticks = total_ticks;
62 m_cpu_previous_idle_ticks = idle_ticks;
63
64 return (rate * 100.0f);
65 }
66#endif
67
68
69 private:
70#if defined(ENIGMA_PLATFORM_WINDOWS)
71
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};
75
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);
78 }
79
80#elif defined(ENIGMA_PLATFORM_LINUX)
81
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};
86
87#elif defined(ENIGMA_PLATFORM_MACOS)
88
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;
93
94#endif
95};
96
97
99
100
101#endif // !ENIGMA_CPU_INFO_H
102
103
104#if 0
105#pragma once
106#ifndef ENIGMA_CPU_INFO_H
107#define ENIGMA_CPU_INFO_H
108
109#undef ENIGMA_PLATFORM_WINDOWS
110#define ENIGMA_PLATFORM_LINUX 1
111
112#include <Core/Core.hpp>
113#include <Logger/Logger.hpp>
114
115#if defined(ENIGMA_PLATFORM_WINDOWS)
116// Windows Includes
117#include <Windows.h>
118#elif defined(ENIGMA_PLATFORM_LINUX)
119// Linux Includes
120#include <cstring>
121#include <sys/times.h>
122#include <sys/vtimes.h>
123#elif defined(ENIGMA_PLATFORM_MACOS)
124// MacOS Includes
125#include <mach/mach_error.h>
126#include <mach/mach_host.h>
127#include <mach/mach_init.h>
128#include <mach/vm_map.h>
129#endif
130
132/*
133* CPUInfo class will gather informations about the CPU at runtime
134*/
135class CPUInfo
136{
137public: /* Constructors / Destructor */
138 CPUInfo() noexcept
139 {
140#if defined(ENIGMA_PLATFORM_WINDOWS)
141 ::SYSTEM_INFO sys_info{};
142 ::FILETIME ftime{}, fsys{}, fuser{};
143
144 ::GetSystemInfo(&sys_info);
145 m_num_processors = sys_info.dwNumberOfProcessors;
146
147 ::GetSystemTimeAsFileTime(&ftime);
148 std::memcpy(&m_last_cpu, &ftime, sizeof(FILETIME));
149
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)
154 std::FILE* file{};
155 struct tms timeSample {};
156 char line[128];
157
158 lastCPU = times(&timeSample);
159 lastSysCPU = timeSample.tms_stime;
160 lastUserCPU = timeSample.tms_utime;
161
162 file = fopen("/proc/cpuinfo", "r");
163 numProcessors = 0;
164 while (fgets(line, 128, file) != NULL) {
165 if (strncmp(line, "processor", 9) == 0) numProcessors++;
166 }
167 fclose(file);
168#endif
169
170 }
171 ~CPUInfo() noexcept = default;
172
175
176
177public:
178 /*
179 * Returns cpu usage (in percentage [0% -> 100%])
180 */
181 float CPUInfo::GetCPUUsage() noexcept
182 {
183 float percentage{ 0.0f };
184
185#if defined(ENIGMA_PLATFORM_WINDOWS)
186
187 if (::GetSystemTimes(&m_idle_time, &m_kernel_time, &m_user_time))
188 {
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);
192 }
193 else
194 percentage = -100.0f;
195
196#elif defined(ENIGMA_PLATFORM_LINUX)
197
198 std::uint64_t total_user{}, total_user_low{}, total_sys{}, total_idle{}, total{};
199
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);
204 std::fclose(file);
205
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)
208 {
209 //Overflow detection. Just skip this value.
210 percentage = -100.0f;
211 }
212 else
213 {
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);
217 percentage /= total;
218 percentage *= 100.0f;
219 }
220
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;
225
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)
228 {
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);
234 }
235 else
236 percentage = -100.0f;
237#endif
238
239 return percentage;
240 }
241
242
243 /*
244 * Returns cpu usage by current process (in percentage [0% -> 100%])
245 */
246 float GetProcessCPUUsage() noexcept
247 {
248#if defined(ENIGMA_PLATFORM_WINDOWS)
249
250 ULARGE_INTEGER now{}, sys{}, user{};
251
252 ::GetSystemTimeAsFileTime(&m_idle_time);
253 std::memcpy(&now, &m_idle_time, sizeof(FILETIME));
254
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));
258
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);
262
263 m_last_cpu = now;
264 m_last_user_cpu = user;
265 m_last_sys_cpu = sys;
266
267 return percent * 100.0f;
268
269#elif defined(ENIGMA_PLATFORM_LINUX)
270#elif defined(ENIGMA_PLATFORM_MACOS)
271#else
272 return 0.0f;
273#endif
274 }
275
276
277private: /* Platform Functions */
278#if defined(ENIGMA_PLATFORM_WINDOWS) || defined(ENIGMA_PLATFORM_MACOS)
279 /*
280 * Calculates CPU Load percentage by idle and total ticks for (used for Windows & MacOS)
281 */
282 float CalculateCPULoad(const std::uint64_t idle_ticks, const std::uint64_t total_ticks)
283 {
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;
286
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);
288
289 m_cpu_previous_total_ticks = total_ticks;
290 m_cpu_previous_idle_ticks = idle_ticks;
291
292 return (rate * 100.0f);
293 }
294#endif
295
296
297private: /* Platform Variables */
298#if defined(ENIGMA_PLATFORM_WINDOWS)
299
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{};
303
304 std::uint64_t m_cpu_previous_total_ticks{ 0 };
305 std::uint64_t m_cpu_previous_idle_ticks{ 0 };
306
307 std::uint64_t FileTimeToUInt64(const FILETIME& file_time)
308 {
309 return (static_cast<std::uint64_t>(file_time.dwHighDateTime) << 32) | static_cast<std::uint64_t>(file_time.dwLowDateTime);
310 }
311
312#elif defined(ENIGMA_PLATFORM_LINUX)
313
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 };
318
319 std::int32_t m_num_processors{};
320
321#elif defined(ENIGMA_PLATFORM_MACOS)
322
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;
327
328#endif
329};
330
331
333
334
335#endif // !ENIGMA_CPU_INFO_H
336#endif
#define NS_ENIGMA_BEGIN
Enable/Disable Assertions.
Definition Macros.hpp:13
#define NS_ENIGMA_END
Definition Macros.hpp:14
#define ENIGMA_NON_MOVEABLE(Class)
Definition Macros.hpp:114
#define ENIGMA_NON_COPYABLE(Class)
Prevent class copying or moving.
Definition Macros.hpp:111
CPUInfo() noexcept
float GetProcessCPUUsage() noexcept
~CPUInfo() noexcept=default
float GetCPUUsage() noexcept