一个C#程序能否以某种方式测量自己的CPU使用率?

40

我正在开发一个后台程序,它将长时间运行,我有一个外部日志记录程序 (SmartInspect),我想定期向其中提供一些值,以便在调试时实时监控。

我知道我可以简单地启动多个程序,例如任务管理器或IARSN TaskInfo,但是我希望在我的程序中保留所有内容,因为我也想添加一些简单的规则,例如如果程序使用了超过 X% 的 CPU,则在日志中标记此事项。

我有一个后台线程,定期向 SmartInspect 提供一些统计信息,例如内存消耗、工作集等。

这个线程是否可以得到一个相当准确的测量,来衡量它占用了计算机的CPU资源的百分比?主程序是单线程应用程序(除了记录统计信息的看门狗线程),因此,如果某种技术仅限于“单个线程使用了多少”,那也很好。

我找到了一些关于 Linux 和 C 中称为 rusage 的东西。是否有类似的东西可以用于此?


编辑:好的,我尝试了性能计数器方式,但每次调用都会增加相当多的 GC 数据,因此内存使用和垃圾回收的图表飙升。我想我现在不加这一部分了。


你在使用完性能计数器后是否已经Close()了它们?- https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.performancecounter.close - ryanwebjackson
5个回答

50

这个效果要好得多,而且对GC的压力增加不大,只是稍微增加了一点。谢谢! - Lasse V. Karlsen
1
@axk 这篇文章似乎不可用,你能否补充一下你的答案,仅指出如何检索当前处理器部分? - J4N

9

请查看 System.Diagnostics.PerformanceCounter。如果你运行 perfmon.exe,你将看到可用于您的性能计数器范围(将“performance object”设置为“Process”),其中之一是“% Processor Time”。


2
这个答案对我来说效果最好。但是我想补充一下:1. 您必须确保每秒或更少地从计数器中仅获取下一个值,否则结果会出错;2. 如果您正在查看CPU统计信息,则必须将其除以Environment.ProcessorCount,否则在8核机器上可能会得到高达800%的疯狂百分比。 - Ben Lesh

4

3
很好,你正在记录像SmartInspect这样的监视器。但是Windows本身会收集每个资源的数据,例如您的程序(或进程)。WMI是应用程序监视的标准。我们可以查看WMI捕获的数据。许多应用程序管理、健康监测或应用程序监视工具都支持WMI。
因此,我不建议您将CPU使用率记录到日志文件中。
如果您认为可用性和性能至关重要,则可以选择Microsoft Operations Manager解决方案。
要了解WMI并获取进程列表,请参见以下内容: - 使用“Win32_PerfFormattedData_PerfProc_Process”获取Cpu时间,过滤器是processID 请参阅此文章 - 您可以从Win32_process类中获取processID。
通过Kevin Matthew Goss的WMI Made Easy For C#来了解WMI。
oConn.Username = "JohnDoe";
oConn.Password = "JohnsPass";

System.Management.ManagementScope oMs = new System.Management.ManagementScope("\\MachineX", oConn);    

//get Fixed disk stats
System.Management.ObjectQuery oQuery = new System.Management.ObjectQuery("select FreeSpace,Size,Name from Win32_LogicalDisk where DriveType=3");

//Execute the query 
ManagementObjectSearcher oSearcher = new ManagementObjectSearcher(oMs,oQuery);

//Get the results
ManagementObjectCollection oReturnCollection = oSearcher.Get();   

//loop through found drives and write out info
foreach( ManagementObject oReturn in oReturnCollection )
{
    // Disk name
    Console.WriteLine("Name : " + oReturn["Name"].ToString());
    // Free Space in bytes
    Console.WriteLine("FreeSpace: " + oReturn["FreeSpace"].ToString());
    // Size in bytes
    Console.WriteLine("Size: " + oReturn["Size"].ToString());
} 

您可以从远程系统监控该过程。

2
这只是一个严格的调试工具,记录日志的代码甚至不会编译到发布版本中。只有方法级别的日志记录将被编译进去,以防我需要在另一台机器上尝试重现奇怪的崩溃。感谢详细的信息,我已经做了记录。 - Lasse V. Karlsen

-2

我不需要计时器,我需要一种方法来测量程序在一段时间内使用了多少CPU,这与花费的时间没有直接关系,例如可能存在阻塞的I/O操作。 - Lasse V. Karlsen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接