I'm trying to roll my own system performance monitor, in order to delay executing parts of my server code in case of overload (running some web services under IIS). The first thing I'm trying to address is the CPU overload.
I know about the PerformanceCounter
issues with having to initialize it with the first call to NextValue()
(see this question, among others), so I implemented a very simple static class that caches the data for a second, and only actually accesses the PerformanceCounter
object once a second or less. I know it's currently not thread-safe, but I'm not concerned with that in the current prototyping phase.
So, having said all that, here's my current code:
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;
}
}
... which is all nice and dandy, until I execute it. I tried running it on a Windows 10 x64 VM with 4 cores, and on Windows 7 x64 iron with 4 cores – and in both cases, the returned value hovers around 400, no matter what I do.
The typical values I get are in the range 395–401, with the occasional dip to 365 or a jump to 405. The values I read are in no way correlated to the actual CPU load on either of the machines I tested, as shown by Task Manager, Performance Monitor, or indeed common sense.
The testing methodology is simple: SystemPerformance.ReadCPU()
is triggered by a button press in a simple Windows form, and the output is shown in a textbox in the same form. I'm pressing that button while the CPU is quasi-idle, and I also press it while other processes are doing stuff and loading the CPU.
What am I doing wrong? Is this supposed to only return the CPU usage by my application's threads? Am I misinterpreting the data?