我今天在工作中被要求为最终用户创建一个工具,以便他们在遇到性能问题时能够运行#34;。这是对经历极端性能问题的若干计算机和/或应用程序的越来越多的报告的反应。由于报告数量众多,我们需要自动进行此数据收集,因此我们可以在以后深入了解数据。
我已经设置了一个收集信息的后端,并且已经收集了大量信息,但是我在收集流程的性能数据时遇到了麻烦。这就是我所看到的:
1)使用System.Diagnotics.Process.GetProcesses():
这让我得到了所有正在运行的proc的列表,这很好,但是这需要应用程序能够显然运行提升,因为它会在我想要收集UserProcessorTime时抛出异常,即使这些信息可用于每个非-admin用户在任务管理器中为自己的进程。即使作为一个成熟的管理员用户运行,它也会抛出异常。
2)使用PerformanceCounter
性能计数器看起来非常强大,但我在按进程ID匹配性能计数器方面遇到了麻烦,看起来性能计数器主要用于跟踪一段时间内的性能。这不是这里的情况。我们主要是在寻找一种过程模式。
基本上,我们正在寻找的(或多或少)是在任务管理器的进程列表中显示的信息的快照(进程名称,cpu周期,私有内存使用情况)并且无需运行提升的应用程序(进程列表可以限制为用户procs)。这符合我的要求。
编辑:这是我尝试使用的一些代码,抱歉没有提供任何早期
这是一个尝试使用性能计数器来获得“处理器时间百分比”的示例。和'工作集 - 私人'适用于所有流程。
PerformanceCounterCategory perfCategory = PerformanceCounterCategory.GetCategories().First(c => c.CategoryName == "Process");
Console.WriteLine("{0} [{1}]", perfCategory.CategoryName, perfCategory.CategoryType);
string[] instanceNames = perfCategory.GetInstanceNames();
if (instanceNames.Length > 0)
{
foreach (string instanceName in instanceNames)
{
Console.WriteLine(" {0}", instanceName);
PerformanceCounter[] counters = perfCategory.GetCounters(instanceName);
foreach (PerformanceCounter counter in counters)
{
if (counter.CounterName == "Working Set - Private")
{
Console.WriteLine(" {0} - {1}", counter.CounterName, counter.RawValue, counter.RawValue / 1024);
}
if (counter.CounterName == "% Processor Time")
{
Console.WriteLine(" {0} - {1}", counter.CounterName, counter.RawValue);
}
}
}
}
'工作集 - 私人'的结果现在已经开始了,但是对于处理器时间而言,这些值没有任何意义。
这是一个输出示例,正如您所看到的,%Processor Time结果没有任何意义:
WDExpress#1
% Processor Time - 378146424
Working Set - Private - 136257536
taskhost
% Processor Time - 129480830
Working Set - Private - 1835008
svchost
% Processor Time - 2877438445
Working Set - Private - 4096000
IpOverUsbSvc
% Processor Time - 15600100
Working Set - Private - 1236992
vncserver
% Processor Time - 238213527
Working Set - Private - 2555904
chrome#21
% Processor Time - 1652830595
Working Set - Private - 56799232
编辑2:
斯科特已经提供了很大一部分答案,但现在我仍然面临以下两个选项的其他问题:快速,不准确,炸弹CPU
counter.NextValue();
Console.WriteLine("{0} - {1}", counter.CounterName, counter.NextValue());
在彼此之后调用NextValue()两次非常快速地收集数据,但是几乎轰炸了我的CPU(并且结果可能是次优的)。
准确,非常慢,很容易在CPU上
counter.NextValue();
System.Threading.Thread.Sleep(1000);
Console.WriteLine("{0} - {1}", counter.CounterName, counter.NextValue());
另一个选项是每次调用NextValue()之间的Thread.Sleep(),但这使得它非常慢(因为我们可能正在讨论100多个进程)
答案 0 :(得分:2)
您处理器时间的问题是您不应该使用RawValue
(您实际上不应该将它用于工作集)。对于处理器时间,您必须调用两个样本NextValue
,一个您获得第二个样本,您将得到准确的数字。
PerformanceCounterCategory perfCategory = PerformanceCounterCategory.GetCategories().First(c => c.CategoryName == "Process");
Console.WriteLine("{0} [{1}]", perfCategory.CategoryName, perfCategory.CategoryType);
string[] instanceNames = perfCategory.GetInstanceNames();
if (instanceNames.Length > 0)
{
foreach (string instanceName in instanceNames)
{
Console.WriteLine(" {0}", instanceName);
PerformanceCounter[] counters = perfCategory.GetCounters(instanceName);
//Go through each processor counter once to get the first value, should just return 0.
foreach (PerformanceCounter counter in counters)
{
if (counter.CounterName == "% Processor Time")
{
counter.NextValue();
}
}
//You need to wait at least 100ms between samples to get useful values, the longer you wait the better the reading.
Thread.Sleep(150);
foreach (PerformanceCounter counter in counters)
{
if (counter.CounterName == "Working Set - Private")
{
Console.WriteLine(" {0} - {1}", counter.CounterName, counter.RawValue, counter.RawValue / 1024);
}
if (counter.CounterName == "% Processor Time")
{
Console.WriteLine(" {0} - {1:N1}", counter.CounterName, counter.NextValue());
}
}
}
}