I'd like to view how the thread loads CPU like it is made in ProcessExplorer. Number of thread CPU cycles can be retrieved by QueryThreadCycleTime
, number of idle cycles - by QueryIdleProcessorCycleTime
, but to know busy cycles I have to reiterate through all processes using QueryProcessCycleTime
that I don't think is very efficient. Is there a simpler method of finding it?
Asked
Active
Viewed 1,276 times
0

Molochnik
- 704
- 5
- 23
-
[How to get the cpu usage per thread on windows (win32)](https://stackoverflow.com/questions/1393006/how-to-get-the-cpu-usage-per-thread-on-windows-win32) – Roman R. Jan 07 '18 at 16:14
-
From this thread: "...But this only gives you the time the thread was spent running". I have permanent threads and I need cycles count, not times. – Molochnik Jan 07 '18 at 16:22
-
Time and cycles are related by a multiplicative factor, the clock frequency – David Heffernan Jan 07 '18 at 19:03
-
But clock frequency can vary @DavidHeffernan (e.g. speedstep, turbo mode), maybe better to offset the cpu time against idle time? – Remko Jan 08 '18 at 13:29
1 Answers
1
but to know busy cycles I have to reiterate through all processes using QueryProcessCycleTime that I don't think is very efficient
It's efficient enough. It takes ~15ms on my machine to enumerate every thread of every process and get its cycle time.
Here's a quick hack which prints top 20 threads by CPU cycles used:
var threads = new Dictionary<int, (DateTime at, ulong ctime, ulong perSec, string procName)>();
var seen = new HashSet<int>();
while (true)
{
var cpuFreq = new ManagementObjectSearcher("select CurrentClockSpeed from Win32_Processor")
.Get().Cast<ManagementObject>().Max(o => (uint) o.Properties["CurrentClockSpeed"].Value) * 1_000_000;
seen.Clear();
var start = DateTime.UtcNow;
foreach (var p in Process.GetProcesses())
{
foreach (var t in p.Threads.Cast<ProcessThread>())
{
if (t.Id == 0)
continue;
seen.Add(t.Id);
var thandle = OpenThread(ThreadAccess.QUERY_INFORMATION, false, (uint) t.Id);
QueryThreadCycleTime(thandle, out ulong ctime);
CloseHandle(thandle);
var at = DateTime.UtcNow;
if (!threads.ContainsKey(t.Id) || threads[t.Id].procName != p.ProcessName)
{
threads[t.Id] = (at: at, ctime: ctime, perSec: 0, procName: p.ProcessName);
}
else
{
var was = threads[t.Id];
var diff = ctime >= was.ctime ? ctime - was.ctime : 0;
threads[t.Id] = (at: at, ctime: ctime, perSec: (ulong) (diff / (at - was.at).TotalSeconds), procName: p.ProcessName);
}
}
}
foreach (var notSeen in threads.Keys.Where(id => !seen.Contains(id)).ToList())
threads.Remove(notSeen);
Console.Clear();
Console.WriteLine($"Time taken to read thread counters: {(DateTime.UtcNow - start).TotalMilliseconds:0} ms");
Console.WriteLine();
Console.WriteLine($"Current CPU clock speed: {cpuFreq / 1_000_000:#,0} MHz");
Console.WriteLine();
foreach (var kvp in threads.OrderByDescending(x => x.Value.perSec).Take(20))
Console.WriteLine($"{kvp.Value.perSec,15:#,0} {kvp.Value.perSec / (double) cpuFreq * 100,3:0}% {kvp.Value.procName + "/" + kvp.Key,-20}");
Thread.Sleep(1000);
}
Output:
Time taken to read thread counters: 15 ms
Current CPU clock speed: 3,801 MHz
1,125,936,851 30% sqlservr/6292
141,635,479 4% sqlservr/6588
106,651,766 3% StatusScreenSite/7656
80,182,644 2% firefox/1880
77,899,627 2% ServiceHub.Host.CLR.x86/12668
74,568,381 2% ServiceHub.Host.CLR.x86/17304
73,911,491 2% AquaComputerService/14840
72,843,646 2% ServiceHub.Host.CLR.x86/13104
64,164,832 2% dwm/1404
46,584,563 1% firefox/14492
46,538,943 1% firefox/17924
44,885,944 1% sqlservr/12880
41,697,624 1% firefox/17164
33,780,283 1% AllThreadCpuUsage/10604 <------- this program
33,165,365 1% ProcessHacker/8588
29,938,943 1% TeamViewer/7356
29,005,700 1% OpenHardwareMonitor/11196
28,808,683 1% nvcontainer/3456
28,536,182 1% nvcontainer/5128
28,294,193 1% svchost/15732
The % column shows % usage of a single core, rather than the entire CPU. Also note that MSDN warns us not to ascribe any particular units to the value returned by thread cycle count, but in practice, on my machine, it returns actual CPU cycles.

Roman Starkov
- 59,298
- 38
- 251
- 324