This is a two-part question, I would like to put my code on the stack here to help others with the same task.
Question 1:
I have a subset of the code that, I believe, correctly measures the CPU usage (through as many cores in the system as possible, as at times) during the measurement interval - I use 1 second in the thread call.
I had to decrypt this from the smallest articles on the Internet and from C ++ code. My question is: for question 1, is this correct, what have I done?
Sometimes the return value is a minus digit, so I multiply by -1. Again, I assume, since there is very little documentation, which I should do.
I have the following code:
public static class Processor { [DllImport("kernel32.dll", SetLastError = true)] static extern bool GetSystemTimes(out ComTypes.FILETIME lpIdleTime, out ComTypes.FILETIME lpKernelTime, out ComTypes.FILETIME lpUserTime); private static TimeSpan _sysIdleOldTs; private static TimeSpan _sysKernelOldTs; private static TimeSpan _sysUserOldTs; static Processor() { } public static void Test() { ComTypes.FILETIME sysIdle, sysKernel, sysUser; if(GetSystemTimes(out sysIdle, out sysKernel, out sysUser)) { TimeSpan sysIdleTs = GetTimeSpanFromFileTime(sysIdle); TimeSpan sysKernelTs = GetTimeSpanFromFileTime(sysKernel); TimeSpan sysUserTs = GetTimeSpanFromFileTime(sysUser); TimeSpan sysIdleDiffenceTs = sysIdleTs.Subtract(_sysIdleOldTs); TimeSpan sysKernelDiffenceTs = sysKernelTs.Subtract(_sysKernelOldTs); TimeSpan sysUserDiffenceTs = sysUserTs.Subtract(_sysUserOldTs); _sysIdleOldTs = sysIdleTs; _sysKernelOldTs = sysKernelTs; _sysUserOldTs = sysUserTs; TimeSpan system = sysKernelDiffenceTs.Add(sysUserDiffenceTs); Double cpuUsage = (((system.Subtract(sysIdleDiffenceTs).TotalMilliseconds) * 100) / system.TotalMilliseconds); if (cpuUsage < 0) { Console.WriteLine("CPU: " + ((int) (cpuUsage)*-1) + "%"); } else { Console.WriteLine("CPU: " + (int) (cpuUsage) + "%"); } Console.WriteLine(""); } else { Console.WriteLine("Couldn't get CPU usage!"); Console.WriteLine(""); } } private static TimeSpan GetTimeSpanFromFileTime(ComTypes.FILETIME time) { return TimeSpan.FromMilliseconds((((ulong)time.dwHighDateTime << 32) + (uint)time.dwLowDateTime) * 0.000001); } }
Question 2:
In any case, for me, synchronizing the thread in my program with the Windows task manager program in order to compare the measurement metric, for example, using the CPU with the above code?
I mean, if you open the Windows task manager, you will notice that it polls every second, which in fact does not have to be less than this. What I want to do is the coincidence of time with my flow.
So, when polling the Windows Task Manager, my polls are threads.
Some notes:
I did not want to use performance counters or .NET built-in methods. In fact, I think - from what I read, .NET has no methods for calculating CPU usage on a machine, it requires performance counters.
Performance counters have overhead and, in addition, increase the GC , not to mention the delay in calling the next result . Although my software does not have to work in real time, I need it to be as responsive and use as little CPU time as possible. The above code can be called and returned in less than a millisecond. In fact, on my development machine, the time difference difference shows 0 ms. I do not believe performance counters are also responsive.
In case you are interested, my software collects several elements, CPU, Memory, Event Log, etc., from which all of them should be collected and saved in SQL CE before the next poll, for 1 second, Each task, element however, is in its flow to facilitate this.
Also, the code above is not optimized anyway, and you will notice that I still need to comment on it. The reason is because I want to make sure that this is correct before optimization, etc.
Update 1
In accordance with my agreement, I deleted the extra βSystemβ time period, since it is not required, and changed the line that retrieves βCPU usageβ and applies it accordingly.
int cpuUsage = (int)(((sysKernelDifferenceTs.Add(sysUserDifferenceTs).Subtract(sysIdleDifferenceTs).TotalMilliseconds) * 100.00) / sysKernelDifferenceTs.Add(sysUserDifferenceTs).TotalMilliseconds);
Although I'm still not sure about the formula. Although it seems to be very accurate, it sometimes returns a minus digit, so I multiply it by -1 if that is the case. In the end, there is no such thing as CPU usage -2%, etc.
Update 2
So, I did a simple test using "System.Diagnostics.PerformanceCounter". Although it is incredibly convenient and does what it is designed for, it creates overhead.
Here are my observations:
- Initialization required a performance counter. Alright, about three seconds longer on the i7 2.6 Ghz.
- The performance counter also seems to have added it to about 5 MB of RAM, just using it. I mean: with the code above, my application is maximized by 7.5 MB of memory. With a performance counter, it "starts" with 12.5 MB.
- For 5 seconds, when my thread was running 5 times - once per second, the memory of my application grew by 1 MB, and this increase is consistent with the time, although it is still aligned, in any case, 3-4 MB above the launch. Therefore, when my application is usually equal to 7.5 MB of RAM with the code above, the PC code is aligned with 16.5 MB of RAM - an increase of 9 MB above the code above. Note: The above code does not increment .
So, if your application was built in such a way that resource usage and timing are key, I would suggest against using performance counters because of these reasons. Otherwise, go ahead, because it works without any mess.
For my application, performance counters will be detrimental to my software.