【问题标题】:Simplest Possible Performance Counter Example最简单的性能计数器示例
【发布时间】:2011-04-23 05:45:01
【问题描述】:

要启动并运行性能计数器,最少需要多少 C# 代码?

我只是想测量代码中两点之间的 CPU 周期数和/或时间。我浏览了网络上所有的华夫饼,但对于这样一个微不足道的任务来说,代码似乎比所需的要多得多。我只想快速启动并运行测量,并更多地专注于我正在做的事情。

【问题讨论】:

    标签: c# performancecounter


    【解决方案1】:

    我认为您不需要为此设置性能计数器。您需要的不仅仅是从StopWatch 获得的时间吗?非常准确。

    Stopwatch watch = Stopwatch.StartNew();
    
    // Do work
    
    watch.Stop();
    // elapsed time is in watch.Elapsed
    

    但是,要回答您实际提出的问题:如果您只想查询现有的计数器,实际上非常简单。这是一个完整的例子:

    using System;
    using System.Diagnostics;
    using System.Linq;
    
    static class Test
    {
        static void Main()
        {
            var processorCategory = PerformanceCounterCategory.GetCategories()
                .FirstOrDefault(cat => cat.CategoryName == "Processor");
            var countersInCategory = processorCategory.GetCounters("_Total");
    
            DisplayCounter(countersInCategory.First(cnt => cnt.CounterName == "% Processor Time"));
        }
    
        private static void DisplayCounter(PerformanceCounter performanceCounter)
        {
            while (!Console.KeyAvailable)
            {
                Console.WriteLine("{0}\t{1} = {2}",
                    performanceCounter.CategoryName, performanceCounter.CounterName, performanceCounter.NextValue());
                System.Threading.Thread.Sleep(1000);
            }
        }
    }
    

    当然,该进程需要适当的权限才能访问您需要的性能计数器。

    【讨论】:

    • 也许我应该详细说明我正在尝试实现一个简单的正则表达式引擎。秒表是否足够准确?
    • @Paul Matthews - 会好的。秒表分辨率以刻度为单位
    • 如果这是您所要求的,它对于测量代码的性能来说已经足够准确了。如果要测量性能,请记住在 Visual Studio 之外以发布模式运行代码。另外,我建议您使用分析器来测量性能,它会告诉您更多关于代码性能的信息,而不仅仅是简单的点对点时间测量。
    • 问:使用性能计数器的最简单方法是什么?答:不要! (哈哈:)
    • 从未有人问过的问题的最佳答案。
    【解决方案2】:

    我喜欢可以采用任何代码块并用秒表分析代码包装它以测量执行它所花费的时间的东西:

        using System.Diagnostics;
        using System.Threading;
    
        public static T Profile<T>(Func<T> codeBlock, string description = "")
        {
            Stopwatch stopWatch = new Stopwatch();
            stopWatch.Start();
            T res = codeBlock();
            stopWatch.Stop();
            TimeSpan ts = stopWatch.Elapsed;
            const double thresholdSec = 2;
            double elapsed = ts.TotalSeconds;
            if(elapsed > thresholdSec)
              System.Diagnostics.Debug.Write(description + " code was too slow! It took " +
                 elapsed + " second(s).");
            return res;
        }
    

    然后这样称呼它:

        Profile(() => MyObj.MySlowMethod());
    

    或:

        Profile(() => MyObj.MySlowMethod(), "I can explain why");
    

    【讨论】:

      【解决方案3】:

      没有简单的方法可以在 .NET 中启动和运行它。然而,我发现的最简单的方法是在企业库之上构建,它提供了一些开箱即用的功能来使用性能计数器。例如:the Performance Counter Handler

      企业库还为您提供了一些功能,可以更轻松地管理性能计数器的安装。

      此外,它让您可以在它之上构建,因此您可以创建一个 AvergeTimeMeter,它允许您这样做:

      private static EnterpriseLibraryPerformanceCounter averageRequestTimeCounter = PerformanceCounterManager.GetEnterpriseLibraryCounter(MadPerformanceCountersListener.AverageRequestTime);
      private static EnterpriseLibraryPerformanceCounter averageRequestTimeCounterBase = PerformanceCounterManager.GetEnterpriseLibraryCounter(MadPerformanceCountersListener.AverageRequestTimeBase);
      
      public void DoSomethingWeWantToMonitor()
      {
          using (new AverageTimeMeter(averageRequestTimeCounter, averageRequestTimeCounterBase))
          {
              // code here that you want to perf mon
          }
      }
      

      这使您可以简单地将要监视的代码封装在 using 块中 - 并专注于您真正想要处理的代码,而不必担心所有性能计数器基础架构。

      为此,您将创建一个可重复使用的 AverageTimeMeter 类,如下所示:

      public sealed class AverageTimeMeter : IDisposable
      {
          private EnterpriseLibraryPerformanceCounter averageCounter;
          private EnterpriseLibraryPerformanceCounter baseCounter;
          private Stopwatch stopWatch;
          private string instanceName;
      
          public AverageTimeMeter(EnterpriseLibraryPerformanceCounter averageCounter, EnterpriseLibraryPerformanceCounter baseCounter, string instanceName = null)
          {
              this.stopWatch = new Stopwatch();
              this.averageCounter = averageCounter;
              this.baseCounter = baseCounter;
              this.instanceName = instanceName;
              this.stopWatch.Start();
          }
      
          public void Dispose()
          {
              this.stopWatch.Stop();
              if (this.baseCounter != null)
              {
                  this.baseCounter.Increment();
              }
      
              if (this.averageCounter != null)
              {
                  if (string.IsNullOrEmpty(this.instanceName))
                  {
                      this.averageCounter.IncrementBy(this.stopWatch.ElapsedTicks);
                  }
                  else
                  {
                      this.averageCounter.SetValueFor(this.instanceName, this.averageCounter.Value + this.stopWatch.ElapsedTicks);
                  }
              }
          }
      
      }
      

      您必须注册您的性能计数器(在 EntLib 示例中显示),但这应该可以让您开始。

      【讨论】:

      • 根据我现在在上面看到的 cmets,您的问题似乎更多地与测量代码有关,而不是 特别是 性能计数器。我总是从性能计数器的角度专门提出问题 - 如果您不需要这个,我同意秒表是最简单的方法。
      • 我最后一次使用性能计数器是在 Delphi 中,所以术语可能发生了一些变化。对不起,如果我把你带到花园小路上:)
      猜你喜欢
      • 2019-05-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-30
      • 2020-03-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多