性能计数器读取访问速度非常慢 - 任务管理器是如何做到的?

Performance Counter read access very slow - How does Task Manager do it?

我正在尝试实施性能监控工具,我想监控内存和 CPU 等基本内容。

我正在尝试通过使用性能计数器来做到这一点,因为我相信这也是任务管理器在幕后使用的。我不知道任务管理器是如何做到这一点的,但是对我来说,使用这种方法检索过程数据似乎需要很长时间:

class Program
    {
        static void Main(string[] args)
        {
            while (true)
            {
                var pcs = Process.GetProcesses()
                    .Select(p => new PerformanceCounter("Process", "Working Set - Private", p.ProcessName));

                var sw = Stopwatch.StartNew();

                foreach (var pc in pcs)
                    pc.NextValue();

                Console.WriteLine($"Time taken to read {pcs.Count()} performance counters: {sw.ElapsedMilliseconds}ms");

                Thread.Sleep(1000);
            }
        }
    }

有没有人对如何执行此操作或任务管理器或进程资源管理器如何执行此操作有任何建议?

How does Task Manager do it?

他曾调用 ZwQuerySystemInformationZwQueryInformationProcessZwQueryInformationThread .. 任务管理器维护活动进程的数据库并通过调用 ZwQuerySystemInformation(SystemProcessInformation,) 定期更新此信息 - 所以在退出时得到 SYSTEM_PROCESS_INFORMATION 数组。 如果发现新进程但不在 DB 中,则添加新条目,删除已死亡进程的条目,更新已存在进程的信息 SYSTEM_PROCESS_INFORMATION 已经包含了很多进程信息。可以通过开放流程获取更多信息,并使用适当的信息 class

调用 ZwQueryInformationProcess

如果你想实现一个性能监控工具,而不需要 "quantum effect"(当测量影响状态本身时)你需要使用这个 ntdll api。有关定义,请查看 http://processhacker.sourceforge.net/doc/ntexapi_8h_source.html 尽管这是未记录的,现有的功能和结构并没有改变 win2000 的最小值(大约 17 年)- windows 的新版本添加了很多新信息 classes,一些字段是 spare/unused 在旧版本中 - 可以使用,但旧的(旧版)没有改变