PerformanceCounter.NextValue() returns 常数值 CPU 负载
PerformanceCounter.NextValue() returns constant value for CPU load
我正在尝试运行我自己的系统性能监视器,以便在过载的情况下延迟执行我的部分服务器代码(运行 IIS 下的某些 Web 服务)。我要解决的第一件事是 CPU 过载。
我知道必须在第一次调用 NextValue()
时初始化它的 PerformanceCounter
问题(参见 this question,等等),所以我实现了一个非常简单的静态 class 将数据缓存一秒钟,实际上仅每秒或更短时间访问一次 PerformanceCounter
对象。我知道它目前不是线程安全的,但在当前的原型设计阶段我并不关心它。
综上所述,这是我当前的代码:
public static class SystemPerformance
{
private static PerformanceCounter TotalProcessorTimeCounter =
new PerformanceCounter("Process", "% Processor Time", "_Total");
private static DateTime CacheRefreshed;
private static float CachedValue = 0f;
private const float MIN_DELTA_SECONDS = 1f;
public static float ReadCPU()
{
if ((DateTime.Now - CacheRefreshed).TotalSeconds > MIN_DELTA_SECONDS)
// Stale cache
return ReadFromCounter();
// Good cache
return CachedValue;
}
private static float ReadFromCounter()
{
CachedValue = TotalProcessorTimeCounter.NextValue();
CacheRefreshed = DateTime.Now;
return CachedValue;
}
}
...在我执行它之前,这一切都很好而且花花公子。我在 Windows 4 核 10 x64 VM 和 Windows 4 核 7 x64 iron 上尝试了 运行 - 在这两种情况下,returned 值都在徘徊400左右,不管我做什么。
我得到的典型值在 395–401 范围内,偶尔会下降到 365 或跳到 405。我读到的值与任何一个上的实际 CPU 负载都没有关系我测试过的机器,如任务管理器、性能监视器所示,或者确实是常识。
测试方法很简单:SystemPerformance.ReadCPU()
由按简单 Windows 形式的按钮触发,输出显示在相同形式的文本框中。我在 CPU 处于准空闲状态时按下该按钮,并且在 其他进程 正在执行操作并加载 CPU 时我也按下了它。
我做错了什么?这是否应该仅 return 我的应用程序线程使用 CPU ?我是否误解了数据?
new PerformanceCounter("Process", "% Processor Time", "_Total");
是的,_Total 进程数占用的处理器时间,包括您在任务管理器中看到的假 "System Idle Process",在 4 核机器上总计为 400%。
如果将 "Process" 更改为 "Processor",您可能会更喜欢这个数字。如果要匹配任务管理器显示的值,则需要将 "Process" 更改为 "Processor Information"。一个新类别,它试图生成一个更真实的数字,以补偿具有涡轮增压的处理器、具有 NUMA 节点的机器以及您从超线程获得的较低性能。您需要阅读 this blog post 以了解细节。
我正在尝试运行我自己的系统性能监视器,以便在过载的情况下延迟执行我的部分服务器代码(运行 IIS 下的某些 Web 服务)。我要解决的第一件事是 CPU 过载。
我知道必须在第一次调用 NextValue()
时初始化它的 PerformanceCounter
问题(参见 this question,等等),所以我实现了一个非常简单的静态 class 将数据缓存一秒钟,实际上仅每秒或更短时间访问一次 PerformanceCounter
对象。我知道它目前不是线程安全的,但在当前的原型设计阶段我并不关心它。
综上所述,这是我当前的代码:
public static class SystemPerformance
{
private static PerformanceCounter TotalProcessorTimeCounter =
new PerformanceCounter("Process", "% Processor Time", "_Total");
private static DateTime CacheRefreshed;
private static float CachedValue = 0f;
private const float MIN_DELTA_SECONDS = 1f;
public static float ReadCPU()
{
if ((DateTime.Now - CacheRefreshed).TotalSeconds > MIN_DELTA_SECONDS)
// Stale cache
return ReadFromCounter();
// Good cache
return CachedValue;
}
private static float ReadFromCounter()
{
CachedValue = TotalProcessorTimeCounter.NextValue();
CacheRefreshed = DateTime.Now;
return CachedValue;
}
}
...在我执行它之前,这一切都很好而且花花公子。我在 Windows 4 核 10 x64 VM 和 Windows 4 核 7 x64 iron 上尝试了 运行 - 在这两种情况下,returned 值都在徘徊400左右,不管我做什么。
我得到的典型值在 395–401 范围内,偶尔会下降到 365 或跳到 405。我读到的值与任何一个上的实际 CPU 负载都没有关系我测试过的机器,如任务管理器、性能监视器所示,或者确实是常识。
测试方法很简单:SystemPerformance.ReadCPU()
由按简单 Windows 形式的按钮触发,输出显示在相同形式的文本框中。我在 CPU 处于准空闲状态时按下该按钮,并且在 其他进程 正在执行操作并加载 CPU 时我也按下了它。
我做错了什么?这是否应该仅 return 我的应用程序线程使用 CPU ?我是否误解了数据?
new PerformanceCounter("Process", "% Processor Time", "_Total");
是的,_Total 进程数占用的处理器时间,包括您在任务管理器中看到的假 "System Idle Process",在 4 核机器上总计为 400%。
如果将 "Process" 更改为 "Processor",您可能会更喜欢这个数字。如果要匹配任务管理器显示的值,则需要将 "Process" 更改为 "Processor Information"。一个新类别,它试图生成一个更真实的数字,以补偿具有涡轮增压的处理器、具有 NUMA 节点的机器以及您从超线程获得的较低性能。您需要阅读 this blog post 以了解细节。