Windows Use vector for performance counter data allocation

This commit is contained in:
Megamouse 2023-05-18 00:10:49 +02:00
commit 4fd21f7764
2 changed files with 31 additions and 18 deletions

View file

@ -2,7 +2,9 @@
#include "util/cpu_stats.hpp" #include "util/cpu_stats.hpp"
#include "util/sysinfo.hpp" #include "util/sysinfo.hpp"
#include "util/logs.hpp" #include "util/logs.hpp"
#include "util/asm.hpp"
#include "Utilities/StrUtil.h" #include "Utilities/StrUtil.h"
#include <algorithm> #include <algorithm>
#ifdef _WIN32 #ifdef _WIN32
@ -80,6 +82,20 @@ namespace utils
#endif #endif
} }
cpu_stats::~cpu_stats()
{
#ifdef _WIN32
if (m_cpu_query)
{
PDH_STATUS status = PdhCloseQuery(m_cpu_query);
if (ERROR_SUCCESS != status)
{
perf_log.error("Failed to close cpu query of per core cpu usage: %s", pdh_error(status));
}
}
#endif
}
void cpu_stats::init_cpu_query() void cpu_stats::init_cpu_query()
{ {
#ifdef _WIN32 #ifdef _WIN32
@ -139,37 +155,35 @@ namespace utils
return; return;
} }
PDH_FMT_COUNTERVALUE counterVal{}; DWORD dwBufferSize = 0; // Size of the items buffer
DWORD dwBufferSize = 0; // Size of the pItems buffer DWORD dwItemCount = 0; // Number of items in the items buffer
DWORD dwItemCount = 0; // Number of items in the pItems buffer
PDH_FMT_COUNTERVALUE_ITEM *pItems = NULL; // Array of PDH_FMT_COUNTERVALUE_ITEM structures
status = PdhGetFormattedCounterArray(m_cpu_cores, PDH_FMT_DOUBLE, &dwBufferSize, &dwItemCount, pItems); status = PdhGetFormattedCounterArray(m_cpu_cores, PDH_FMT_DOUBLE, &dwBufferSize, &dwItemCount, nullptr);
if (PDH_MORE_DATA == status) if (PDH_MORE_DATA == status)
{ {
pItems = (PDH_FMT_COUNTERVALUE_ITEM*)malloc(dwBufferSize); std::vector<PDH_FMT_COUNTERVALUE_ITEM> items(utils::aligned_div(dwBufferSize, sizeof(PDH_FMT_COUNTERVALUE_ITEM)));
if (pItems) if (items.size() >= dwItemCount)
{ {
status = PdhGetFormattedCounterArray(m_cpu_cores, PDH_FMT_DOUBLE, &dwBufferSize, &dwItemCount, pItems); status = PdhGetFormattedCounterArray(m_cpu_cores, PDH_FMT_DOUBLE, &dwBufferSize, &dwItemCount, items.data());
if (ERROR_SUCCESS == status) if (ERROR_SUCCESS == status)
{ {
ensure(dwItemCount > 0); ensure(dwItemCount == per_core_usage.size() + 1); // Plus one for _Total
ensure((dwItemCount - 1) == per_core_usage.size()); // Remove one for _Total
// Loop through the array and get the instance name and percentage. // Loop through the array and get the instance name and percentage.
for (DWORD i = 0; i < dwItemCount; i++) for (usz i = 0; i < dwItemCount; i++)
{ {
const std::string token = wchar_to_utf8(pItems[i].szName); const PDH_FMT_COUNTERVALUE_ITEM& item = items[i];
const std::string token = wchar_to_utf8(item.szName);
if (const std::string lower = fmt::to_lower(token); lower.find("total") != umax) if (const std::string lower = fmt::to_lower(token); lower.find("total") != umax)
{ {
total_usage = pItems[i].FmtValue.doubleValue; total_usage = item.FmtValue.doubleValue;
continue; continue;
} }
if (const auto [success, cpu_index] = string_to_number(token); success && cpu_index < dwItemCount) if (const auto [success, cpu_index] = string_to_number(token); success && cpu_index < dwItemCount)
{ {
per_core_usage[cpu_index] = pItems[i].FmtValue.doubleValue; per_core_usage[cpu_index] = item.FmtValue.doubleValue;
} }
else if (!success) else if (!success)
{ {
@ -188,10 +202,9 @@ namespace utils
} }
else else
{ {
perf_log.error("Failed to allocate buffer for per core cpu usage."); perf_log.error("Failed to allocate buffer for per core cpu usage. (size=%d, dwItemCount=%d)", items.size(), dwItemCount);
} }
} }
if (pItems) free(pItems);
#elif __linux__ #elif __linux__
@ -362,8 +375,7 @@ namespace utils
entry.dwSize = sizeof(entry); entry.dwSize = sizeof(entry);
// get the first process info. // get the first process info.
BOOL ret = true; BOOL ret = Process32First(snapshot, &entry);
ret = Process32First(snapshot, &entry);
while (ret && entry.th32ProcessID != id) while (ret && entry.th32ProcessID != id)
{ {
ret = Process32Next(snapshot, &entry); ret = Process32Next(snapshot, &entry);

View file

@ -28,6 +28,7 @@ namespace utils
public: public:
cpu_stats(); cpu_stats();
~cpu_stats();
double get_usage(); double get_usage();