TotalProcessorTime differs between Windows 10 and Windows 11

Martin Dijkstra 20 Reputation points
2023-02-22T13:16:43.94+00:00

For our applications we use the Process.GetCurrentProcess().TotalProcessorTime to determine how much CPU is used for actions calls.

When an action takes 1 second to execute and only performs cpu operations, we except 1 second of cpu time.

For Windows 10 this works as expected, for Windows 11 the cpu usage is always 30/50% lower.

This behavior applies to .net framework and .net 6 applications

Below is a test application to reproduce the problem.

using System;
using System.Diagnostics;
using System.Threading.Tasks;

_ = Task.Run(() => ConsumeCPU());

while (true)
{
    await PrintCpuUsage();
}

static void ConsumeCPU()
{
    while (true) ;
}

static async Task PrintCpuUsage()
{
    var startTime = DateTime.UtcNow;
    var startCpuUsage = Process.GetCurrentProcess().TotalProcessorTime;

    await Task.Delay(1000);

    var endTime = DateTime.UtcNow;
    var endCpuUsage = Process.GetCurrentProcess().TotalProcessorTime;

    var cpuUsedMs = (int)(endCpuUsage - startCpuUsage).TotalMilliseconds;
    var totalMsPassed = (int)(endTime - startTime).TotalMilliseconds;
    Console.Clear();
    Console.WriteLine($"CPU:{cpuUsedMs}ms Watch:{totalMsPassed}ms");
}
Windows 10
Windows 10
A Microsoft operating system that runs on personal computers and tablets.
11,696 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
11,001 questions
Windows 11
Windows 11
A Microsoft operating system designed for productivity, creativity, and ease of use.
9,861 questions
{count} votes

Accepted answer
  1. Gary Nebbett 6,081 Reputation points
    2023-03-02T14:41:02.7566667+00:00

    Hello Martin,

    I think that I am getting closer to understanding what is happening and that suggests to me that you will have to update your performance analysis techniques.

    Using ETW under Windows 10, one often sees sequences of events like this:

    User's image

    The first clock interrupt entry is the hardware clock interrupt; the lower bit of the final value for that entry indicates that this processor (0) is the clock owner. The next two clock interrupt entries occur as a result of an interprocessor interrupt (IPI) - this can be verified by examining the stacks for the three clock interrupt events. The clock interrupt is forwarded, via IPI, to all processors that are not "idle".

    This behaviour gives the results for CPU usage time that you have observed up to Windows 10.

    Under Windows 11, I see this:

    User's image

    User's image

    The differences are that a new bit (mask 0x10) is set on all clock interrupt events and clock interrupt events always occur just once per "tick" (i.e. no instances of clock interrupt events separated by tenths of microseconds on different processors).

    This could just be an artefact of ETW tracing under Windows 11, but it ties in nicely with the observed behaviour of the thread/process CPU usage counters. More work is needed...

    Gary


6 additional answers

Sort by: Most helpful
  1. red-ray 1 Reputation point
    2023-04-13T13:50:44.3766667+00:00
    1. I have also noticed W10 and W11 are different, not only GetThreadTimes(), but also NtQuerySystemInformation( SystemProcessorPerformanceInformation, ...). I also looked at what NtQuerySystemInformation( SystemProcessorIdleInformation...) returned on W11 and the two IdleTime can be different on W11, but not on W10.
    2. When the Kernel mode load is low the two idle times are almost the same, but once there is a high Kernel load they are very different. I added some code to my SIV utility to show the effect and on W11 from at least build 22621 through to 25336 see this issue. Below is an image I created showing the two idle times, notice they are different. This only happens on W11 22H2 and later, and not on W10.
    3. As the Idle Time is higher than it should be and the Kernel Time includes the Idle time the effective Kernel Time is lower than it should be, often it's zero. I suspect this is the root cause of GetThreadTimes() returning different values on W11.
    4. I changed my code to replace the incorrect Idle Time from SystemProcessorPerformanceInformation with the value from SystemProcessorIdleInformation. This is why the plots on the main panel show a high % of Kernel time.
    5. In summary I suspect the root cause of these issues must be a bug in the Windows 11 kernel that Microsoft need to fix.
    6. RCR
    7. I also see the same issue on my W11 22621 22H2 system.
    8. RAV
    9. I do not see the issue on this system, so maybe it's related to hyperthreading
    10. RCX

  2. red-ray 1 Reputation point
    2023-08-25T21:48:03.54+00:00

    As I suspected this was a bug in Windows 11. I know this as it's been fixed in todays 23H2 Build 25936 and my test proves this as the two idle times are now much the same.

    RCR

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.