PerformanceCounter创建需要很长时间。

7
我是一名有用的助手,以下是您需要翻译的内容:

我正在开发一个充电平衡系统,因此我需要知道每台机器的电荷。 PerformanceCounter 似乎是不错的选择,但创建第一个计数器需要花费38到60秒。然而,每个后续的新计数器或“NextValue”调用几乎是即时的。

这是我正在使用的代码:

[TestClass]
public class PerfMon
{
    [TestMethod]
    public void SimpleCreationTest()
    {
        Stopwatch Time = new Stopwatch();
        Time.Start();
        Debug.WriteLine("Time is : " + Time.ElapsedMilliseconds);

        // Create

        PerformanceCounter RAM = new PerformanceCounter("Memory", "Available MBytes");
        Debug.WriteLine("Time is : " + Time.ElapsedMilliseconds + " => RAM created");

        PerformanceCounter CPU = new PerformanceCounter("Processor", "% Processor Time", "_Total");
        Debug.WriteLine("Time is : " + Time.ElapsedMilliseconds + " => CPU created");

        PerformanceCounter GC = new PerformanceCounter(".NET CLR Memory", "% Time in GC", "_Global_");
        Debug.WriteLine("Time is : " + Time.ElapsedMilliseconds + " => GC created");

        // Read

        float Value = RAM.NextValue();
        Debug.WriteLine("Time is : " + Time.ElapsedMilliseconds + " => RAM value is : " + Value);

        Value = CPU.NextValue();
        Debug.WriteLine("Time is : " + Time.ElapsedMilliseconds + " => CPU value is : " + Value);

        Value = GC.NextValue();
        Debug.WriteLine("Time is : " + Time.ElapsedMilliseconds + " => GC value is : " + Value);
    }
}

研究

连接远程服务器时PerformanceCounter非常慢

创建新的System.Diagnostics.PerformanceCounter非常慢

我尝试使用其他构造函数并提供精确的"MachineName",但它并没有改变任何东西。

为什么PerformanceCounter的调用很慢?

http://craigandera.blogspot.fr/2005/06/performancecounter-constructor-horribly_21.html

根据这两个线程,问题似乎与性能计数器是共享资源有关。然而,我不知道如何解决这个问题。

以管理员身份运行Visual Studio会将第一个创建加速从38秒缩短到26秒,因此也无法解决问题。


谢谢你的帮助。


尝试通过公共静态变量实现PerformanceCounter实例,如此处所示:http://msdn.microsoft.com/en-us/library/system.diagnostics.performancecounter%28v=vs.110%29.aspx - JunaidKirkire
这已经是我的“真实”类的工作方式了 - 这也是我发现问题的方式。在上面的测试代码中将PerformanceCounter设置为“static public”并没有改变任何东西。 - Epineurien
似乎是网络问题和身份验证问题的结合。NextValue()方法文档确实提到了这一点 -要读取性能计数器,必须具有管理员特权。在Windows Vista中,用户帐户控制(UAC)确定用户的特权。如果您是内置管理员组的成员,则分配两个运行时访问令牌:标准用户访问令牌和管理员访问令牌。默认情况下,您处于标准用户角色。 - JunaidKirkire
2
那么……成为管理员可以“解决”身份验证问题,但不能解决网络问题?我不明白为什么网络会在这里扮演任何角色,因为我正在请求本地性能。使用“没有机器名称”的构造函数,构造函数甚至不必查找本地机器之外的内容。无论如何,使用此链接:http://www.sevenforums.com/tutorials/7539-local-users-groups-manager-open.html,我已经成功将PerformanceCounter创建时间延长到26秒,而无需以管理员身份启动VS。但是“网络问题”仍然毫无意义。这很奇怪。 - Epineurien
2
哦,我不知道它是在本地运行的。所以肯定“网络问题”没有意义。 - JunaidKirkire
2个回答

3
我在我的机器上尝试了你的代码,构造函数的性能计数器需要超过2.5秒的时间。我无法调试.NET源代码(我正在运行VS2013 Express Edition,Windows 7 64b),但我进行了一系列实验:
  1. 我调用了性能计数器的默认构造函数。它立即执行。
  2. 使用perfmon检查与网络相关的活动。我没有看到任何异常。
  3. 我监控了内存占用情况。当我调用第一个参数化的构造函数时,我将大约增加2.5MB的内存占用。
  4. 使用perfmon检查是否有使用互斥量、信号量和其他同步对象的数量激增。没有发生异常情况。
  5. 我在不同的进程活动时测试了代码。我发现存在很大的变化。有时我得到1.4秒,有时我得到2.7秒,有时我得到5秒。
  6. 我已经打开了GUI监控会话并运行了代码,但我没有看到任何收益。
所以我相信没有设置问题,答案是“PerformanceCounter构造函数执行复杂工作,需要很长时间才能执行”。
所有被监视的事件都是可以由操作系统跟踪的软件事件。因此,我认为当创建新的PerformanceCounter对象时,“操作系统必须生成当前机器的状态”。这可能意味着获取所有进程的信息,最重要的是将该信息存储到可读且快速可访问的结构中。我观察到“我拥有的越活跃的进程,PerformanceCounter创建得越慢”。此外,你拥有的处理器核心越多,可能需要收集的数据也就越多。
在你发送的最后一个链接中,有一条评论似乎验证了这个理论,但我认为自2005年以来,自旋锁部分已经被优化了。也许最后的手段是调试.NET源代码以构建PerformanceCounter。然而,我认为这只是它的实现方式。
我会在应用程序的初始化阶段创建所需的性能计数器对象。

简而言之,创建 PerformanceCounter 时会产生成本。使用缓存来重复使用相同的 .NET 实例。 - user2864740
此外,缓存的性能计数器甚至不需要对应原始进程(这是另一个关联问题,但是...),只有InstanceName是相关的。尝试访问不存在的实例的计数器将简单地抛出“InvalidOperationException”:“指定类别中不存在实例'..'。” - user2864740

0

这是解决我的方法:

通过确保它作为64位进程执行,我的应用程序中的性能计数器设置时间从2:30分钟降至约20秒。有趣的是,我只在Windows 2012虚拟机中遇到了性能问题,在Windows 10中没有任何问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接