C# 性能计数器NextValue()非常慢(1000个计数器)
在我们的应用程序中,我们使用Windows性能计数器来存储一些应用程序指标,这些指标稍后将在一些web服务中检索 我对从计数器读取值所需的时间有问题。我已经浏览了我的应用程序的其余部分,一切都很好,从性能上看,但是从循环中的计数器(从列表或数组)读取数据需要很长时间 示例代码: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
// 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
- 值得注意的是,计数器必须读取两次,因为许多计数器是在一段时间内计算的,并且呈现开始和结束读取时间之间的平均值,因此在实际场景中,这些错误数字会变得更糟
在处理大量额外计数器时,需要注意的是,您需要解决默认情况下为性能计数器设置的内存限制。这可以通过machine.config或注册表项完成。更多信息可以在这里找到:出于好奇,如果使用普通的foreach循环,性能会如何
foreach(counters.ToList()中的var counter){counter.NextValue();}
@keyboard这与LINQ将生成的有很大不同吗?@FreeAsInBeer-不,不应该是,只是想了解问题的基本部分。这并不完全是小事。您是从本地计算机读取性能计数器数据,还是?也许您可以从foreach循环内部秒表,记录每个计数器的时间,并向我们提供该信息。也许知道谁是170ms'ers,谁是0ms'ers会给我们一个答案