我想查看线程如何加载CPU,就像在ProcessExplorer中一样。 QueryThreadCycleTime
可以检索线程CPU周期数,空闲周期数为QueryIdleProcessorCycleTime
,但要了解繁忙周期,我必须使用QueryProcessCycleTime
重复所有进程,我不会这样做; t认为非常有效率。是否有更简单的方法可以找到它?
答案 0 :(得分:0)
但是要了解繁忙的周期,我必须使用QueryProcessCycleTime重申所有我认为不是非常有效的过程
足够有效。在我的计算机上需要大约15毫秒来枚举每个进程的每个线程并获取其循环时间。
这是一个快速的技巧,可以按所使用的CPU周期显示前20个线程:
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);
}
输出:
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
%列显示单个内核而不是整个CPU的使用百分比。还请注意,MSDN警告我们不要将任何特定单位归因于线程周期计数返回的值,但实际上,在我的计算机上,它会返回实际的CPU周期。