【问题标题】:PerformanceCounter creation take a LONG timePerformanceCounter 创建需要很长时间
【发布时间】:2014-04-13 09:46:58
【问题描述】:

我正在研究电荷平衡系统,因此我需要知道每台机器的电荷。 PerformanceCounter 似乎是要走的路,但创建第一个需要 38 到 60 秒。然而,每个后续的新 Counter 或“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 extremely slow in connecting remote server

Creating a new System.Diagnostics.PerformanceCounter is very slow

我尝试使用其他构造函数并给出精确的“机器名称”,但它并没有改变任何东西。

Why a call to PerformanceCounter is slow?

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

根据这两个线程,问题似乎在于性能计数器是共享资源这一事实。但是我不明白我该如何解决。

在管理员中运行 Visual Studio 将第一次创建从 38 秒“加速”到 26 秒,因此它也不能解决问题。


感谢您的帮助。

【问题讨论】:

  • 尝试通过公共静态变量实现 PerformanceCounter 实例,如下所示msdn.microsoft.com/en-us/library/…
  • 这就是我的“真实”课堂的工作方式——以及我发现问题的方式。在上面的测试代码中将 PerformanceCounter 设置为“静态公共”并没有改变任何内容。
  • 这似乎是网络问题加上身份验证问题。 NextValue() 方法文档确实提到了这一点 - 要读取性能计数器,您必须具有管理权限。在 Windows Vista 中,用户帐户控制 (UAC) 确定用户的权限。如果您是 Built-in Administrators 组的成员,则会为您分配两个运行时访问令牌:一个标准用户访问令牌和一个管理员访问令牌。默认情况下,您是标准用户角色。
  • 所以...作为管理员“解决”身份验证问题而不是网络问题?我不明白为什么在我请求本地性能时网络会在这里发挥任何作用。使用“无机器名称”构造函数,构造函数甚至不必查看本地机器外部。无论如何,使用这个:sevenforums.com/tutorials/… 我已经能够在不以管理员身份启动 VS 的情况下将 PerformanceCounter 创建时间缩短到 26 秒。但是“网络问题”仍然没有意义。这很奇怪。
  • 哦,我不知道它在本地运行。所以是的,network issue 绝对没有意义。

标签: c# performance load-balancing performancecounter shared-resource


【解决方案1】:

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

  1. 我调用了 PerformanceCounter 的 默认构造函数。它会立即执行。
  2. 我使用 perfmon 检查了 networking 相关活动。我没有看到任何奇怪的东西。
  3. 我监控了内存占用。我看到在调用第一个参数化构造函数时,我在代码的内存占用中增加了 ~2.5MB。
  4. 使用 perfmon 我检查了使用的互斥锁、信号量和其他同步对象的计数是否出现峰值。没有发生任何异常情况。
  5. 我在不同数量的进程处于活动状态时多次测试了代码。我看到有变化很大。有时我得到 1.4 秒,有时我得到 2.7 有时我得到 5 秒。
  6. 我已经打开了一个 GUI 监控会话并运行了代码,但我没有看到任何收获。

所以我认为不存在设置问题,答案是 PerformanceCounter 构造函数做了复杂的工作,需要花费大量时间来执行

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

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

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

【讨论】:

  • tldr; 创建 PerformanceCounter 时的成本。使用 缓存 重复使用相同的性能计数器 .NET 实例。
  • 此外,缓存的性能计数器甚至不需要对应原始进程(这是关联的另一个问题,但是..),只有 InstanceName 是相关的。尝试访问不再存在的实例的计数器只会抛出InvalidOperationException:“指定类别中不存在实例'..'。”
【解决方案2】:

这是为我解决的问题:

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

【讨论】:

    猜你喜欢
    • 2013-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多