C# PerformanceCounter创建需要很长时间

C# PerformanceCounter创建需要很长时间,c#,performance,load-balancing,performancecounter,shared-resource,C#,Performance,Load Balancing,Performancecounter,Shared Resource,我正在研究电荷平衡系统,因此我需要知道每台机器的电荷。PerformanceCounter似乎是一种方法,但创建第一个需要38到60秒。然而,每个后续的新计数器或“NextValue”调用几乎都是即时的 以下是我正在使用的代码: [TestClass] public class PerfMon { [TestMethod] public void SimpleCreationTest() { Stopwatch Time = new Stopwatch()

我正在研究电荷平衡系统,因此我需要知道每台机器的电荷。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);
    }
}
研究

我尝试使用其他构造函数并给出一个精确的“MachineName”,但它没有改变任何东西

根据这两个线程,问题似乎与性能计数器是共享资源这一事实有关。但是我不明白我怎么能解决这个问题

在Administrator中运行Visual Studio将第一次创建从38秒“加速”到26秒,因此也无法解决问题



谢谢你的帮助。

我在我的机器上尝试了你的代码,我得到了>2.5秒的性能计数器的构造函数时间。我无法调试.NET源代码(我运行的是VS2013 Express Edition,Windows 7 64b),但我做了一系列实验:

  • 我调用了PerformanceCounter的默认构造函数。它立即执行
  • 我使用perfmon检查了网络相关活动。我没看到什么奇怪的东西
  • 我监控了内存占用。我看到在调用第一个参数化构造函数时,我在代码的内存占用中添加了~2.5MB
  • 使用perfmon,我检查使用的互斥、信号量和其他同步对象的计数是否出现峰值。没有什么不寻常的事情发生
  • 当不同数量的进程处于活动状态时,我在不同的时间测试了代码。我看到有很大的变化。有时我得到1.4秒,有时我得到2.7秒,有时我得到5秒
  • 我已经打开了一个GUI监控会话并运行了代码,但没有看到任何收益
  • 因此,我相信不存在设置问题,答案是PerformanceCounter构造函数执行复杂的工作,需要花费大量时间来执行

    所有被监视的事件都是软件事件,可由操作系统跟踪。因此,我假设在创建新的PerformanceCounter对象时,操作系统必须生成机器的当前状态。这可能意味着获取所有进程的信息,最重要的是,将这些信息存储到可读且快速可访问的结构中。我观察到的是,我拥有的流程越活跃,创建PerformanceCounter的速度就越慢。而且,您拥有的内核越多,可能需要收集的数据就越多

    在您发送的上一个链接中,有一条评论似乎验证了这一理论,但我认为spinlock部分自2005年以来就进行了优化。最后的措施可能是调试.NET源代码以构建PerformanceCounter。然而,我认为这就是它的实现方式


    我要做的是在应用程序的初始化阶段创建所需的PerformanceCounter对象。

    这就是我所做的:


    我的应用程序中的性能计数器设置时间从2:30分钟减少到20秒左右,因为它确保以64位进程执行。有趣的是,我只在Windows2012虚拟机中遇到了性能问题。Windows 10中没有问题。

    尝试通过公共静态变量实现PerformanceCounter实例,如图所示,这已经是我的“真实”类的工作方式,也是我发现问题的方式。在上面的测试代码中将PerformanceCounter设置为“静态公共”并没有改变任何事情。这似乎是一个网络问题加上身份验证问题。NextValue()方法文档确实提到了这一点——要读取性能计数器,您必须具有管理权限。在Windows Vista中,用户帐户控制(UAC)决定用户的权限。如果您是内置Administrators组的成员,则会为您分配两个运行时访问令牌:标准用户访问令牌和管理员访问令牌。默认情况下,您处于标准用户角色。因此。。。作为管理员“解决”身份验证问题,而不是网络问题?我不明白为什么网络会在这里扮演任何角色,因为我要求本地性能。使用“No machine name”构造函数,构造函数甚至不必查看本地计算机之外的内容。无论如何,使用这个:我已经能够在不以管理员身份启动VS的情况下将PerformanceCounter创建时间缩短到26秒。但“网络问题”仍然毫无意义。这很奇怪。哦,我不知道它在本地运行。因此,是的,
    网络问题显然毫无意义;创建PerformanceCounter时的成本。使用缓存可重复使用相同的性能计数器.NET实例。此外,缓存的性能计数器甚至不需要与原始进程相对应(这是关联的另一个问题,但是…),并且只有InstanceName相关。尝试访问不再存在的实例的计数器只会抛出一个
    InvalidOperationException
    :“指定类别中不存在实例“..”