Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 性能计数器NextValue()非常慢(1000个计数器)_C#_.net_Performancecounter_Perfmon - Fatal编程技术网

C# 性能计数器NextValue()非常慢(1000个计数器)

C# 性能计数器NextValue()非常慢(1000个计数器),c#,.net,performancecounter,perfmon,C#,.net,Performancecounter,Perfmon,在我们的应用程序中,我们使用Windows性能计数器来存储一些应用程序指标,这些指标稍后将在一些web服务中检索 我对从计数器读取值所需的时间有问题。我已经浏览了我的应用程序的其余部分,一切都很好,从性能上看,但是从循环中的计数器(从列表或数组)读取数据需要很长时间 示例代码: // This triggers a read of the counter's initial value (1000ms delay following for calculated counters) counte

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

我对从计数器读取值所需的时间有问题。我已经浏览了我的应用程序的其余部分,一切都很好,从性能上看,但是从循环中的计数器(从列表或数组)读取数据需要很长时间

示例代码:

// This triggers a read of the counter's initial value (1000ms delay following for calculated counters)
counters.ToList().ForEach(counter => counter.NextValue());
在我对上面循环的测试中,1359个计数器的列表需要20秒,在秒表就位的情况下,读取计数器值的平均时间似乎是0-10ms,或者大约80-90ms。很多都需要0毫秒,最高约为170毫秒,平均非零约为80-90毫秒

也许我过于乐观了,但我认为读取1000个数值只需要几毫秒。这里进行的处理是否比我所知道的要多得多

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

谢谢


更新1 我把计数器装在秒表里,结果令我惊讶。即使是读取
.RawValue
的简单属性也需要花费大量的时间。据我所知,计数器的工作原理基本相同,检索速度应该非常快;奇怪的是,我也看到了一种模式,即网络类别的计数器需要更长的时间

根据我们的观点,性能计数器服务的性能甚至不应该成为一个考虑因素

我已将一些秒表结果发布到以下pastebin:

我的代码如下:

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

正如您在粘贴中看到的,很多读取是0,但在50-100ms范围内有很多读取。我真的不明白怎么会这样。当然,一个计数器值应该和其他计数器值一样快,对吗?

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

  • 从计数器类别中读取实例名称至少需要4-5秒的处理时间(在服务器上可能更好,也可能更差,不确定)。这随类别中计数器的数量变化很小。如果不使用实例计数器,可以避免这种情况
  • 我们将所有计数器存储在一个类别中,因此,考虑到我们的情况,该类别最终不可避免地会有数千个计数器。在我的测试中,类别中的计数器越多,性能越差。这似乎是有道理的,但单个计数器的性能受内存中当前计数器数量的影响,这是一种奇数相关性,可能:
    • 共有8个计数器,每个计数器的读取时间约为1-2ms
    • 总共256个计数器,每个计数器的读取时间约为15-18ms
    • 总共有512个计数器,每个计数器的读取时间约为30毫秒
    • 共有3584个计数器(读取所有计数器),每个计数器的读取时间约为200ms
    • 系统中总共有3584个计数器(在内存中过滤,只读取512个计数器),每个计数器的读取时间在50-90毫秒之间。不确定为什么这些计数器比前一批512个计数器慢
    • 我使用
      System.Diagnostics.Stopwatch
      对这些测试进行了几次计时
  • 值得注意的是,计数器必须读取两次,因为许多计数器是在一段时间内计算的,并且呈现开始和结束读取时间之间的平均值,因此在实际场景中,这些错误数字会变得更糟
根据上面的数字,在我的机器上,512个计数器在较慢的一端大约50毫秒,加上实例查询和第二个计数器读取,我们看到每个请求大约60秒。这是因为我们一次只能使用512个计数器。我已经在我的机器上对服务运行了多次完整的查询,请求始终在60-65秒内完成

我当然不会根据正在评估的其他计数器的数量来假设单个计数器的这种性能下降。在我看来,Windows性能监视系统应该是快速的,而且对于小集合来说,它当然是快速的。我们的用例可能不适合,我们可能滥用了系统

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


在处理大量额外计数器时,需要注意的是,您需要解决默认情况下为性能计数器设置的内存限制。这可以通过machine.config或注册表项完成。更多信息可以在这里找到:

出于好奇,如果使用普通的foreach循环,性能会如何
foreach(counters.ToList()中的var counter){counter.NextValue();}
@keyboard这与LINQ将生成的有很大不同吗?@FreeAsInBeer-不,不应该是,只是想了解问题的基本部分。这并不完全是小事。您是从本地计算机读取性能计数器数据,还是?也许您可以从foreach循环内部秒表,记录每个计数器的时间,并向我们提供该信息。也许知道谁是170ms'ers,谁是0ms'ers会给我们一个答案