【发布时间】:2012-08-23 05:57:25
【问题描述】:
我正在考虑制作一个改进版的 Windows 资源监视器,它不仅包括资源使用情况,还包括硬件状态,例如温度和风扇速度。
我昨天开始使用 c++ 对其进行编程,并且我已经成功地列出并刷新了我计算机上每个进程的内存和 CPU 利用率。
但是,问题来了:它非常慢。每秒轮询一次使用情况时,它使用了我的 i5 2500k@4.3 GHz 的 5%。这是不可接受的,因为我不仅想要 CPU 和内存使用情况,还想要每个硬盘驱动器的磁盘使用情况、互联网使用情况、GPU 使用情况(每个进程的所有这些),然后我还想监控所有温度。
这是我的代码:
const double MB = 1024*1024;
const double KB = 1024;
struct WinProcess
{
wstring Name;
unsigned int ID;
wstring UserName;
double cpuUsage;
long long int ramUsage;
WinProcess(wstring name, unsigned int id) : Name(name), ID(id), UserName(L"Not set"), cpuUsage(0), ramUsage(0) {}
};
class ResourceMonitor
{
private:
void** hquery;
void** hcountercpu;
void** hcountermem;
int cpuCores;
vector<WinProcess> Processes;
public:
ResourceMonitor();
~ResourceMonitor();
void StartResourceMonitor();
void MeasureResourceUsage();
void PrintUsage();
};
ResourceMonitor::ResourceMonitor() :
Processes(GetProcessList()) // Function GetProcessList() returns vector with all processes, their IDs and username, from which it was launched
{
hquery = new void*[Processes.size()];
hcountercpu = new void*[Processes.size()];
hcountermem = new void*[Processes.size()];
for (unsigned int i = 2; i < Processes.size(); i++)
{
Processes[i].Name = Processes[i].Name.substr(0, Processes[i].Name.size() - 4);
}
for (unsigned int i = 2; i < Processes.size(); i++)
{
wstring CounterPathCPU = L"\\Process(" + Processes[i].Name + L")\\% Processor Time";
wstring CounterPathMEM = L"\\Process(" + Processes[i].Name + L")\\Private Bytes";
if ((PdhOpenQuery(NULL, 0, &hquery[i])) != ERROR_SUCCESS
|| PdhAddCounter(hquery[i], CounterPathCPU.c_str(), 0, &hcountercpu[i]) != ERROR_SUCCESS
|| PdhAddCounter(hquery[i], CounterPathMEM.c_str(), 0, &hcountermem[i]) != ERROR_SUCCESS
|| PdhCollectQueryData(hquery[i]) != ERROR_SUCCESS)
{
continue;
}
}
SYSTEM_INFO sysinfo;
GetSystemInfo(&sysinfo);
cpuCores = sysinfo.dwNumberOfProcessors;
wcout.setf(ios::fixed);
}
ResourceMonitor::~ResourceMonitor()
{
for (unsigned int i = 2; i < Processes.size(); i++)
{
PdhCloseQuery(hquery[i]);
PdhRemoveCounter(hcountercpu[i]);
PdhRemoveCounter(hcountermem[i]);
}
delete[] hquery;
delete[] hcountercpu;
}
void ResourceMonitor::StartResourceMonitor()
{
system("mode CON: COLS=150");
while (1)
{
MeasureResourceUsage();
PrintUsage();
Sleep(1000);
}
}
void ResourceMonitor::MeasureResourceUsage()
{
PDH_FMT_COUNTERVALUE countervalcpu;
PDH_FMT_COUNTERVALUE countervalmem;
for (unsigned int i = 2; i < Processes.size(); i++)
{
if ((PdhCollectQueryData(hquery[i])) != ERROR_SUCCESS)
{
printError(L"Error on collecting query data: ");
continue;
}
if ((PdhGetFormattedCounterValue(hcountercpu[i], PDH_FMT_LONG | PDH_FMT_NOCAP100, 0, &countervalcpu)) != ERROR_SUCCESS)
{
printError(L"Error on CPU usage retrieval: ");
continue;
}
if ((PdhGetFormattedCounterValue(hcountermem[i], PDH_FMT_LONG, 0, &countervalmem)) != ERROR_SUCCESS)
{
printError(L"Error on Memory usage retrieval: ");
continue;
}
Processes[i].cpuUsage = countervalcpu.longValue / (double)cpuCores;
Processes[i].ramUsage = countervalmem.longValue;
}
}
void ResourceMonitor::PrintUsage()
{
system("cls");
long long int RAMSUM = 0;
for (unsigned int i = 2; i < Processes.size(); i++)
{
wcout << left << setw(40) << Processes[i].Name + L".exe: ";
wcout << setw(6) << left << L" | ID " << setw(4) << right << Processes[i].ID;
wcout << setw(8) << left << L" | User " << setw(15) << Processes[i].UserName;
wcout << setw(8) << left << L" | CPU usage " << setw(10) << right << setprecision(2) << Processes[i].cpuUsage << setw(1) << L"%";
wcout << setw(8) << left << L" | RAM usage " << setw(15) << right << setprecision(3) << Processes[i].ramUsage / MB << setw(3) << left << L" MB" << endl;
RAMSUM += Processes[i].ramUsage;
}
wcout << L"Total RAM usage: " << setw(7) << right << RAMSUM / MB
<< setw(3) << left << L" MB" << endl;
}
我很清楚这段代码存在的问题:进程列表永远不会更新,也没有 GUI,但这些都是可以修复的,因为获取进程列表功能非常快。
有没有办法像 Windows 任务管理器那样检查 CPU 和内存使用任务?我可以使用 c++ 或 c#,因为我知道这两种语言。最后,我不知道如何监控每个进程的网络流量、磁盘使用情况和 GPU 使用情况。有任何想法吗?感谢您的帮助!
【问题讨论】:
-
我在这里遗漏了一些东西,它使用了我的处理器的 5%,并且彼此之间非常慢?如果您希望它更快,一旦您消除了任何愚蠢的错误,它将使用更多的处理器而不是更少。一些分析可能会有所帮助,这需要“太长时间”。猜测不会把你带到任何地方。
-
该程序应在后台运行。它甚至不应该使用我 1% 的 CPU。考虑到我的速度非常快,它确实会降低 CPU 速度较慢的计算机的性能。慢一点是这个函数:void ResourceMonitor::MeasureResourceUsage()
-
几年前我写了一个程序来做这个并且消耗最少的资源。但是直到大约 8 小时后我才能访问代码。如果到那时您还没有答案,我将发布我使用的答案。 (谷歌 StartWatch,该程序将是第一个热门)
-
只是为了获得一个基线,您应该尝试在所有 printf 和其他控制台输出注释掉的情况下运行您的程序(但程序仍在执行所有工作)以确保输出不是问题.
-
我已经试过了。 CPU 使用率并没有像预期的那样下降,因为每 1000 毫秒打印 50 行并不是那么多工作:)。