microsoft / Windows-Dev-Performance

A repo for developers on Windows to file issues that impede their productivity, efficiency, and efficacy
MIT License
434 stars 20 forks source link

Windows incorrectly schedules utility QoS threads exclusively to E-cores when running on AC power #117

Open conioh opened 6 months ago

conioh commented 6 months ago

Windows Build Number

22631

Processor Architecture

AMD64

Memory

64GB

Storage Type, free / capacity

SSD 4TB

Relevant apps installed

WinDbg, LiveKD

Traces collected via Feedback Hub

https://aka.ms/AAojvh6

Isssue description

Windows incorrectly schedules utility QoS threads exclusively to E-cores when running on AC power.

Steps to reproduce

[C:\]
> cd C:\Windows\Temp\
[C:\Windows\Temp]
> $sieve_URI = "https://github.com/kimwalisch/primesieve/releases/download/v11.2/primesieve-11.2-win-x64.zip"
[C:\Windows\Temp]
> Invoke-WebRequest -Uri $sieve_URI -OutFile "sieve.zip"
[C:\Windows\Temp]
> Expand-Archive -Path ".\sieve.zip" -DestinationPath ".\sieve\"
[C:\Windows\Temp]
> schtasks.exe /Create /SC ONLOGON /TN "PrimeSieve" /TR "C:\Windows\Temp\sieve\primesieve.exe 1e12" /NP
SUCCESS: The scheduled task "PrimeSieve" has successfully been created.
[C:\Windows\Temp]
> schtasks.exe /Run /TN "PrimeSieve"
SUCCESS: Attempted to run the scheduled task "PrimeSieve".
[C:\Windows\Temp]
>

Expected Behavior

Windows should schedule utility QoS processes/threads exclusively to E-core only when running on battery power. When running on AC power the default behavior should be kept.

According to the documentation of a company called Microsoft (archive):

QoS level Utility Description Background services Performance and power On battery, selects most efficient CPU frequency and schedules to efficient cores. Release Windows 11 22H2

image

Actual Behavior

Windows schedules the process's threads to run only on the E-cores:

image

Taking a dump using livekd.exe while primesieve.exe is running allows us to verify the thread QoS:

0: kd> dx Debugger.Sessions[0].Processes.Where( p => p.Name == "primesieve.exe" ).First().Threads.Select( t => t.KernelObject.Tcb.BamQosLevel )
Debugger.Sessions[0].Processes.Where( p => p.Name == "primesieve.exe" ).First().Threads.Select( t => t.KernelObject.Tcb.BamQosLevel )                
    [0x9bac]         : 0x6 [Type: unsigned long]
    [0x215c]         : 0x6 [Type: unsigned long]
    [0x9978]         : 0x6 [Type: unsigned long]
    [0x7e84]         : 0x6 [Type: unsigned long]
    [0x5fc8]         : 0x6 [Type: unsigned long]
    [0x5f20]         : 0x6 [Type: unsigned long]
    [0xf6c]          : 0x6 [Type: unsigned long]
    [0x5a38]         : 0x6 [Type: unsigned long]
    [0x5aa8]         : 0x6 [Type: unsigned long]
    [0xa2b4]         : 0x6 [Type: unsigned long]
    [0x574c]         : 0x6 [Type: unsigned long]
    [0x67c4]         : 0x6 [Type: unsigned long]
    [0x5af4]         : 0x6 [Type: unsigned long]
    [0xa6d8]         : 0x6 [Type: unsigned long]
    [0x301c]         : 0x6 [Type: unsigned long]
    [0xa270]         : 0x6 [Type: unsigned long]
    [0x42d8]         : 0x6 [Type: unsigned long]
    [0x378]          : 0x6 [Type: unsigned long]
    [0xed4]          : 0x6 [Type: unsigned long]
    [0x84d0]         : 0x6 [Type: unsigned long]
    [0x2968]         : 0x6 [Type: unsigned long]

And as we all know 6 means KHeteroCpuQosUtility.