From 8e1a01215dbbf64e2e242688a6f93553392453cc Mon Sep 17 00:00:00 2001 From: DevWiki Date: Mon, 30 Sep 2024 18:21:09 +0800 Subject: [PATCH] add perf --- WinDevice/src/Utils/PerformanceTool.cpp | 175 ++++++++++++++++++++++++ WinDevice/src/Utils/PerformanceTool.h | 47 +++++++ WinDevice/src/Utils/StringUtil.cpp | 70 ++++++++++ WinDevice/src/Utils/StringUtil.h | 29 ++-- WinDevice/src/main.cpp | 23 +++- 5 files changed, 323 insertions(+), 21 deletions(-) create mode 100644 WinDevice/src/Utils/PerformanceTool.cpp create mode 100644 WinDevice/src/Utils/PerformanceTool.h create mode 100644 WinDevice/src/Utils/StringUtil.cpp diff --git a/WinDevice/src/Utils/PerformanceTool.cpp b/WinDevice/src/Utils/PerformanceTool.cpp new file mode 100644 index 0000000..bf9010c --- /dev/null +++ b/WinDevice/src/Utils/PerformanceTool.cpp @@ -0,0 +1,175 @@ +// +// Created by zyz on 2024/9/30. +// + +#include "PerformanceTool.h" +#include "../Utils/StringUtil.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#pragma comment(lib, "PowrProf.lib") +#pragma comment(lib, "pdh.lib") + +WinDevice::PerformanceTool::PerformanceTool() { + +} + +WinDevice::PerformanceTool::~PerformanceTool() { + +} + +float WinDevice::PerformanceTool::GetAppCpuUsage(DWORD processId) { + return _GetAppCpuUsage(processId, _GetProcessName(processId)); +} + +float WinDevice::PerformanceTool::GetAppCpuUsage(const std::wstring &processName) { + return _GetAppCpuUsage(_GetProcessId(processName), processName); +} + +float WinDevice::PerformanceTool::_GetAppCpuUsage(DWORD processId, const std::wstring &processName) { + HQUERY query; + PDH_HCOUNTER cpuCounter; + PDH_FMT_COUNTERVALUE counterVal; + TCHAR szCounterPath[MAX_PATH]; + + // 初始化PDH + if (PdhOpenQuery(NULL, 0, &query) != ERROR_SUCCESS) { + return 1; + } + + // 构造CPU计数器路径 + _stprintf_s(szCounterPath, MAX_PATH, TEXT("\\Process V2(%s:%d)\\%% Processor Time"), WinDevice::Wstring2String(processName).c_str(), processId); + if (PdhAddCounter(query, szCounterPath, 0, &cpuCounter) != ERROR_SUCCESS) { + PdhCloseQuery(query); + return 1; + } + + PdhCollectQueryData(query); + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); // 等待以获取更新数据 +// 再次收集数据 + PdhCollectQueryData(query); + + // 读取计数器值 + auto cpuUsage = 0.0; + auto result = PdhGetFormattedCounterValue(cpuCounter, PDH_FMT_DOUBLE, NULL, &counterVal); + if (result == ERROR_SUCCESS) { + cpuUsage = counterVal.doubleValue; + } + + // 清理 + // 关闭句柄 + PdhRemoveCounter(cpuCounter); + PdhCloseQuery(query); + return cpuUsage; +} + +float WinDevice::PerformanceTool::GetAppMemoryUsage(const std::wstring &processName) { + return _GetAppMemoryUsage(processName); +} + +float WinDevice::PerformanceTool::GetAppMemoryUsage(DWORD processId) { + return _GetAppMemoryUsage(_GetProcessName(processId)); +} + +float WinDevice::PerformanceTool::_GetAppMemoryUsage(const std::wstring &processName) { + HQUERY query; + PDH_HCOUNTER memCounter; + PDH_FMT_COUNTERVALUE counterVal; + TCHAR szCounterPath[MAX_PATH]; + + // 初始化PDH + if (PdhOpenQuery(NULL, 0, &query) != ERROR_SUCCESS) { + return 1; + } + + // 构造内存计数器路径 + _stprintf_s(szCounterPath, MAX_PATH, TEXT("\\Process(%s)\\%s"), processName.c_str(), TEXT("Working Set - Private")); + if (PdhAddCounter(query, szCounterPath, 0, &memCounter) != ERROR_SUCCESS) { + PdhCloseQuery(query); + return 1; + } + + PdhCollectQueryData(query); + + auto memoryUsage = 0.0; + auto result = PdhGetFormattedCounterValue(memCounter, PDH_FMT_DOUBLE, NULL, &counterVal); + if (result == ERROR_SUCCESS) { + memoryUsage = counterVal.doubleValue / 1024.0 / 1024.0; + } + + // 清理 + // 关闭句柄 + PdhRemoveCounter(memCounter); + PdhCloseQuery(query); + return memoryUsage; +} + +std::wstring WinDevice::PerformanceTool::_GetProcessName(DWORD processId) { + std::wstring processName = L""; // 使用 std::wstring + HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processId); + if (hProcess != nullptr) { + HMODULE hMod; + DWORD cbNeeded; + + // 获取进程中的模块句柄 + if (EnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded)) { + // 获取模块的可执行文件名 + TCHAR name[MAX_PATH]; + GetModuleBaseName(hProcess, hMod, name, sizeof(name) / sizeof(TCHAR)); + + // 去掉 .exe 后缀 + TCHAR* dot = _tcsrchr(name, '.'); + if (dot != nullptr && _tcscmp(dot, TEXT(".exe")) == 0) { + *dot = '\0'; // 将 '.' 及其后面的字符替换为 '\0' + } + + processName = WinDevice::TCHARArrayToWString(name); // 转换为 std::wstring + } + CloseHandle(hProcess); // 确保在这里关闭句柄 + } + + // 打印进程名称 + std::wcout << L"Current process name: " << processName << std::endl; + return processName; // 返回 std::wstring +} + +DWORD WinDevice::PerformanceTool::_GetProcessId(const std::wstring &processName) { + DWORD processId = 0; + //创建进程快照 + HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (hSnapshot == INVALID_HANDLE_VALUE) + { + return 0; + } + + PROCESSENTRY32 pe; + pe.dwSize = sizeof(PROCESSENTRY32); + +// 遍历所有进程 + if (Process32First(hSnapshot, &pe)) + { + do + { + // 将进程名与目标进程名进行比较 + if (_tcscmp(pe.szExeFile, WinDevice::Wstring2String(processName).c_str()) == 0) + { + processId = pe.th32ProcessID; + break; + } + } while (Process32Next(hSnapshot, &pe)); + } + return processId; +} diff --git a/WinDevice/src/Utils/PerformanceTool.h b/WinDevice/src/Utils/PerformanceTool.h new file mode 100644 index 0000000..d1ae359 --- /dev/null +++ b/WinDevice/src/Utils/PerformanceTool.h @@ -0,0 +1,47 @@ +// +// Created by zyz on 2024/9/30. +// +#include +#include +#include +#include +#include + +#ifndef WINDEVICE_PERFORMANCETOOL_H +#define WINDEVICE_PERFORMANCETOOL_H + +namespace WinDevice { + + struct AppUsageInfo { + DWORD processId; + std::string processName; + float cpuUsage; + float memoryUsage; + }; + + class PerformanceTool { + public: + PerformanceTool(); + ~PerformanceTool(); + float GetAppCpuUsage(DWORD processId); + float GetAppCpuUsage(const std::wstring& processName); + float GetAppMemoryUsage(DWORD processId); + float GetAppMemoryUsage(const std::wstring& processName); +// float GetCurrentAppCpuUsage(); +// float GetCurrentAppMemoryUsage(); +// WinDevice::AppUsageInfo GetCurrentAppUsage(); +// WinDevice::AppUsageInfo GetAppUsage(DWORD processId); +// WinDevice::AppUsageInfo GetAppUsage(const std::wstring& processName); +// std::vector GetTopAppUsageInfo(int topCount); +// float GetTotalCpuUsage() const; +// float GetTotalMemoryUsage() const; + + private: + float _GetAppCpuUsage(DWORD processId, const std::wstring &processName); + float _GetAppMemoryUsage(const std::wstring &processName); + std::wstring _GetProcessName(DWORD processId); + DWORD _GetProcessId(const std::wstring &processName); + }; +} + +#endif //WINDEVICE_PERFORMANCETOOL_H diff --git a/WinDevice/src/Utils/StringUtil.cpp b/WinDevice/src/Utils/StringUtil.cpp new file mode 100644 index 0000000..d2ca5b4 --- /dev/null +++ b/WinDevice/src/Utils/StringUtil.cpp @@ -0,0 +1,70 @@ +// +// Created by zyz on 2024/9/30. +// + +#ifndef WINDEVICE_STRINGUTIL_CPP_H +#define WINDEVICE_STRINGUTIL_CPP_H + +#include "StringUtil.h" +#include +#include +#include +#include + +template +To Convert(const From &input) { + std::wstring_convert, typename From::value_type> converter; + try { + return converter.to_bytes(input); + } catch (...) { + return To(); // 返回空对象 + } +} + +std::string WinDevice::Wstring2String(const std::wstring &input) { + return Convert(input); +} + +std::string WinDevice::Wchar2String(const WCHAR *input) { + std::wstring_convert> converter; + try { + return converter.to_bytes(input); + } catch (...) { + return ""; // 返回空字符串表示失败 + } +} + +std::wstring WinDevice::String2Wstring(const std::string &input) { + std::wstring_convert> converter; + try { + return converter.from_bytes(input); + } catch (...) { + return L""; // 返回空宽字符串表示失败 + } +} + +wchar_t *WinDevice::String2Wchar(const std::string &input) { + std::wstring wstr = String2Wstring(input); + if (wstr.empty()) { + return nullptr; // 转换失败时返回 nullptr + } + wchar_t *wcharStr = new wchar_t[wstr.length() + 1]; + std::wcscpy(wcharStr, wstr.c_str()); + return wcharStr; // 返回动态分配的 wchar_t* +} + +// 通用转换函数 +std::wstring WinDevice::TCHARArrayToWString(const TCHAR *tcharArray) { +#ifdef UNICODE + return std::wstring(tcharArray); // 如果是 Unicode,直接返回 +#else + // 如果是 ANSI,进行转换 + int size_needed = MultiByteToWideChar(CP_ACP, 0, tcharArray, -1, nullptr, 0); + std::wstring wstrName(size_needed, L'\0'); // 创建足够大小的 std::wstring + MultiByteToWideChar(CP_ACP, 0, tcharArray, -1, &wstrName[0], size_needed); + return wstrName; +#endif +} + + +#endif //WINDEVICE_STRINGUTIL_CPP_H diff --git a/WinDevice/src/Utils/StringUtil.h b/WinDevice/src/Utils/StringUtil.h index 5d59224..c8ed15a 100644 --- a/WinDevice/src/Utils/StringUtil.h +++ b/WinDevice/src/Utils/StringUtil.h @@ -1,22 +1,13 @@ -#include -#include -#include +#pragma once +#include +#include namespace WinDevice { + + std::string Wstring2String(const std::wstring& input); + std::string Wchar2String(const WCHAR* input); + std::wstring String2Wstring(const std::string& input); + wchar_t* String2Wchar(const std::string& input); + std::wstring TCHARArrayToWString(const TCHAR* tcharArray); - template - To Convert(const From& input) { - std::wstring_convert, typename From::value_type> converter; - return converter.to_bytes(input); - } - - std::string Wstring2String(const std::wstring& input) { - return Convert(input); - } - - std::string Wchar2String(const WCHAR* input) { - std::wstring_convert> converter; - return converter.to_bytes(input); - } - -} +} \ No newline at end of file diff --git a/WinDevice/src/main.cpp b/WinDevice/src/main.cpp index 4ad13e0..4fe9d64 100644 --- a/WinDevice/src/main.cpp +++ b/WinDevice/src/main.cpp @@ -2,11 +2,30 @@ // Created by zyz on 2023/12/20. // #include +#include #include "Video/ScreenManager.h" +#include "Utils/PerformanceTool.h" + +void getInfo() { + + WinDevice::PerformanceTool performanceTool; + + while (true) { + + std::cout << "App CPU Usage: " << performanceTool.GetAppCpuUsage(L"XYWinQT.pak") << "%" << std::endl; + + // 每隔一秒采样一次(如果需要的话) + std::this_thread::sleep_for(std::chrono::seconds(1)); + } +} + int main() { - WinDevice::ScreenManager screenManager; - screenManager.UpdateDisplayInfo(); +// WinDevice::ScreenManager screenManager; +// screenManager.UpdateDisplayInfo(); + getInfo(); std::cout << "Press Enter to exit..." << std::endl; // 输出提示信息 std::cin.get(); // 等待用户输入 return 0; } + +