gpt4 book ai didi

c# - 查询进程性能计数器的最有效方法是什么?

转载 作者:可可西里 更新时间:2023-11-01 14:40:36 26 4
gpt4 key购买 nike

我正在尝试实现一个性能监控工具,我想监控内存和 CPU 等基本事物。

我正在尝试通过使用性能计数器来做到这一点,因为我相信这是在 C# 中查询进程性能的“正确”方式,这是一些示例代码:

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);
}
}
}

enter image description here

很明显,在我的系统上查询一个进程需要大约 12.5 毫秒,慢得令人无法接受。应该怎么做?

我已经在这篇文章中提出了一个相关问题:Performance Counter read access very slow - How does Task Manager do it?

但我意识到我在那篇文章中不够具体并且问错了问题。我真正想知道的是如何使用性能计数器完成我想做的事情,还是根本不可能?

编辑1:

我运行的是 Windows 10 Pro 1607 - Build 14393.479

最佳答案

每当您对机器上所有正在运行的进程执行某项操作时,Windows 都会变得缓慢,这是出了名的。但这是过分的。 PerformanceCounter 的状态有些问题,我从 this question 得到了第一个提示.通过更改 Console.WriteLine() 调用,您可以在自己的测试程序中轻松地将其可视化:

  Console.Write($"Time taken to read {pcs.Count()} performance counters:");
Console.WriteLine($"{sw.ElapsedMilliseconds}ms, {GC.CollectionCount(2)} collections");

我机器上的输出:

Time taken to read 124 performance counters: 1633ms, 15 collections
Time taken to read 124 performance counters: 923ms, 30 collections
Time taken to read 124 performance counters: 928ms, 45 collections
Time taken to read 124 performance counters: 934ms, 59 collections
Time taken to read 124 performance counters: 922ms, 74 collections
Time taken to read 124 performance counters: 925ms, 89 collections
...etc

或者换句话说,对每 ~8 次调用 PerformanceCounter.NextValue() 进行一次完整垃圾回收。哎哟。是的,这会使您的程序陷入困境。

委婉地说,这是非常奇怪的行为。我在 PerformanceCounter 类本身找不到任何好的线索,代码看起来很无辜。引擎盖下有一大块非托管代码很难看到 (C:\Windows\Microsoft.NET\Framework\v4.0.30319\PerfCounter.dll) 但查看其依赖项并不能提供令人信服的证据证明它是负责任的。这在 v2.0.50727 和 v4.0.30319 运行时版本上都会发生,因此 V4.x 中的不幸 hack 无法轻易解释它。它不是 8 的整数倍,因此强制终结器运行的简单计数器并不能轻易解释它。它不是 native 性能计数器,使用 WMI 查询它不会触发任何收集。它不特定于内存计数器,查询“线程计数”也是如此。可能和Windows版本有关系,我的是Win10版本1607(不能轻易测试另一个)。

Microsoft 需要参与其中。我链接的问题的作者似乎创建了一个 bug feedback report for it ,我加了这个Q+A作为佐证。密切关注反馈报告,为其投票,希望他们会开始关注。如果您不想等待,也可以直接联系 Microsoft 支持。


与此同时,您可以继续使用 System.Management 命名空间。 WMI Code Creator 实用程序非常方便自动生成代码:

...
using System.Management; // Project > Add Reference required

public static void QueryWorkingset() {
ManagementObjectSearcher searcher =
new ManagementObjectSearcher("root\\CIMV2",
"SELECT Name, WorkingSetPrivate FROM Win32_PerfRawData_PerfProc_Process");
foreach (ManagementObject queryObj in searcher.Get()) {
Console.WriteLine("{0}: {1}", queryObj["Name"], queryObj["WorkingSetPrivate"]);
}
}

仍然没有速度恶魔,在我的机器上每个进程大约需要 1.0 毫秒。但不会像 PerformanceCounter 那样消耗 100% 的核心,也不会强制收集。

关于c# - 查询进程性能计数器的最有效方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41006521/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com