gpt4 book ai didi

c# - 性能计数器 NextValue() 非常慢(1,000 多个计数器)

转载 作者:太空狗 更新时间:2023-10-29 18:31:37 24 4
gpt4 key购买 nike

在我们的应用程序中,我们使用 Windows 性能计数器来存储我们的一些应用程序指标,这些指标稍后会在某些 Web 服务中检索。

我对从计数器读取值所花费的时间有疑问。我查看了我的应用程序的其余部分,一切都很好,性能方面,但在循环中(从列表或数组)读取计数器需要花费大量时间。

示例代码:

// This triggers a read of the counter's initial value (1000ms delay following for calculated counters)
counters.ToList().ForEach(counter => counter.NextValue());

在我对上面的循环的测试中,1,359 个计数器的列表需要 20 秒,并且在秒表就位的情况下,读取计数器值的平均时间似乎是 0-10 毫秒,或者大约 80-90 毫秒。很多都是0ms,最高的是170ms左右,非零的平均是80-90ms左右。

也许我太乐观了,但我认为读取 1,000 个数值应该只需要几毫秒。这里进行的处理是否比我意识到的要多得多?

我的逻辑后面实际上还有另一个循环,它为计算的计数器获取第二个值。这只会让事情变得更糟。 :)

谢谢!


更新1

我将计数器检索包裹在秒表中,我对结果感到惊讶。甚至读取 .RawValue 的简单属性仍然需要花费大量时间。据我了解,计数器的工作原理基本相同,检索速度应该非常快;奇怪的是,我还看到了一种模式,其中网络类别的计数器需要更长的时间。

根据 http://joe.blog.freemansoft.com/2014/03/windows-performance-counters.html ,甚至不应该考虑性能计数器服务的性能。

我已经将一些秒表结果发布到以下 pastebin:http://pastebin.com/raw.php?i=aDJk2Tru

我的代码如下:

Stopwatch t;
foreach (var c in counters)
{
t = Stopwatch.StartNew();
var r = c.RawValue;
Debug.WriteLine(t.ElapsedMilliseconds.ToString("000") + " - " + c.CategoryName + ":" + c.CounterName + "(" + c.CounterType + ") = " + r);
}

贴子里可以看到,很多reads都是0,但是50-100ms范围内也有很多。我真的不明白那怎么可能。当然,一个计数器值应该和其他任何计数器值一样快,对吧?

最佳答案

以下是我能够找到的有关计数器的信息。请原谅语法;这是从我发出的有关此问题的电子邮件中摘录的。

  • 有 4-5 秒的处理时间,至少在我的机器上(在服务器上可能更好或更差,不确定),以从计数器类别中读取实例名称。这与类别中计数器的数量变化可以忽略不计。如果您不使用实例计数器,则可以避免这种情况。
  • 我们将所有计数器存储在一个类别中,因此鉴于我们的情况,该类别最终将不可避免地包含数千个计数器。在我的测试中,一个类别中的计数器越多,性能越差。这似乎是有道理的,但是单个计数器的性能受当前内存中计数器数量的影响,这是一个奇怪的相关性,也许:
    • 总共有 8 个计数器,每个计数器的读取时间约为 1-2 毫秒
    • 总共有 256 个计数器,每个计数器的读取时间约为 15-18 毫秒
    • 总共有 512 个计数器,每个计数器的读取时间约为 30 毫秒
    • 总共有 3,584 个计数器(读取所有计数器),每个计数器的读取时间约为 200 毫秒
    • 系统中共有 3,584 个计数器(在内存中过滤,仅读取 512 个计数器),每个计数器的读取时间为 50-90 毫秒。不知道为什么这些比前一批 512 计数器慢。
    • 我使用 System.Diagnostics.Stopwatch 对每个测试进行了几次计时。
  • 值得注意的是,计数器必须被读取两次,因为许多计数器是在一段时间内计算的,并且呈现开始和结束读取时间之间的平均值,因此这些错误的数字在现实世界中变得更糟场景。

鉴于上面的数字,在我的机器上,在较慢的一端有 512 个计数器,每个计数器大约 50 毫秒,加上实例查询和第二个计数器读取,我们看到每个请求大约需要 60 秒。这是因为我们一次只处理 512 个计数器。我在我的机器上针对该服务多次运行完整查询,请求始终在 60-65 秒内完成。

我当然不会根据正在评估的其他计数器的数量来假设单个计数器的这种类型的性能下降。在我的阅读中,Windows Performance Monitor 系统应该很快,而且对于小集合来说确实如此。我们的用例可能不适合,我们可能在滥用系统。

更新

鉴于我们可以控制我们创建计数器的方式,我们决定稍微改变我们的方法。我们创建了许多类别,而不是几个具有许多计数器的类别,每个类别具有更少的计数器(每个类别 4-8 个计数器)。这种方法使我们能够有效地避免性能问题,并且计数器读取时间在 0-1ms 范围内。根据我们目前的经验,即使有 100 个新类别,每个类别都有几个计数器,也不会影响系统的性能。

请务必注意,在处理大量附加计数器时,您需要解决默认为性能计数器设置的内存限制。这可以通过 machine.config 或注册表项来完成。可以在此处找到更多信息:http://msdn.microsoft.com/en-us/library/ms229387(v=vs.110).aspx

关于c# - 性能计数器 NextValue() 非常慢(1,000 多个计数器),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25372073/

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