【问题标题】:Measure execution time in C#在 C# 中测量执行时间
【发布时间】:2011-04-23 15:00:40
【问题描述】:

我想测量一段代码的执行情况,我想知道最好的方法是什么?

选项 1:

DateTime StartTime = DateTime.Now;

//Code

TimeSpan ts = DateTime.Now.Subtract(StartTime);
string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
        ts.Hours, ts.Minutes, ts.Seconds,
        ts.Milliseconds / 10);
Console.WriteLine(elapsedTime, "RunTime");

选项 2: 使用 System.Diagnostics;

    Stopwatch stopWatch = new Stopwatch();
    stopWatch.Start();

    //Code

    stopWatch.Stop();
    // Get the elapsed time as a TimeSpan value.
    TimeSpan ts = stopWatch.Elapsed;

    // Format and display the TimeSpan value.
    string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
        ts.Hours, ts.Minutes, ts.Seconds,
        ts.Milliseconds / 10);
    Console.WriteLine(elapsedTime, "RunTime");

这不仅仅是为了进行基准测试,它实际上是应用程序的一部分。函数执行的时间是相关数据。然而,它不需要是原子的或超精确的。

哪个选项更适合生产代码,或者其他人使用不同的东西,也许更好?

【问题讨论】:

  • 好问题!我很好奇答案!

标签: c# datetime execution-time measure


【解决方案1】:

我采用 Hamish 的回答对其进行了简化,并使其更加通用,以防您需要登录到其他地方:

public class AutoStopWatch : Stopwatch, IDisposable {

    public AutoStopWatch() {
        Start();
    }

    public virtual void Dispose() {
        Stop();
    }
}

 public class AutoStopWatchConsole : AutoStopWatch {

    private readonly string prefix;

    public AutoStopWatchConsole(string prefix = "") {
        this.prefix = prefix;
    }

    public override void Dispose() {
        base.Dispose();

        string format = Elapsed.Days > 0 ? "{0} days " : "";
        format += "{1:00}:{2:00}:{3:00}.{4:00}";

        Console.WriteLine(prefix + " " + format.Format(Elapsed.Days, Elapsed.Hours, Elapsed.Minutes, Elapsed.Seconds, Elapsed.Milliseconds / 10));
    }
}

private static void Usage() {

    Console.WriteLine("AutoStopWatch Used: ");
    using (var sw = new AutoStopWatch()) {
        Thread.Sleep(3000);

        Console.WriteLine(sw.Elapsed.ToString("h'h 'm'm 's's'"));
    }

    Console.WriteLine("AutoStopWatchConsole Used: ");
    using (var sw = new AutoStopWatchConsole()) {
        Thread.Sleep(3000);
    }

}

【讨论】:

    【解决方案2】:

    Stopwatch 类专门用于测量经过的时间,并且可以(如果在您的硬件上可用)使用底层高频硬件计时器提供良好的粒度/准确性。所以这似乎是最好的选择。

    IsHighResolution property 可用于确定高分辨率时序是否可用。根据文档,此类为“最佳可用”Win32 API 提供了一个包装器,以实现准确的计时:

    具体来说,Frequency 字段和 GetTimestamp 方法可用于 非托管 Win32 API 的位置 QueryPerformanceFrequencyQueryPerformanceCounter.

    [这里] 和链接的 MSDN 文档2 中有这些 Win32 API 的详细背景。

    高分辨率计时器

    计数器是一个通用术语,用于 编程指的是 递增变量。一些系统 包括高分辨率性能 提供高分辨率的计数器 经过的时间。

    如果有高分辨率的表现 系统上存在计数器,您可以 使用 QueryPerformanceFrequency 表示频率的函数,在 每秒计数。的价值 计数取决于处理器。一些 处理器,例如,计数 可能是循环率 处理器时钟。

    QueryPerformanceCounter 函数 检索当前值 高分辨率性能计数器。 通过在 一段的开始和结束 代码,应用程序本质上使用 计数器作为高分辨率 计时器。例如,假设 QueryPerformanceFrequency 表示 的频率 高分辨率性能计数器是 每秒 50,000 次计数。如果 应用程序调用 QueryPerformanceCounter 立即 之前和之后 要计时的代码部分, 计数器值可能是 1500 个计数 和 3500 个计数。这些 值将表明 0.04 秒 (2000 次计数)代码已过 执行。

    【讨论】:

    • Stopwatch 还使用高分辨率计时器(如果可用),这在测量执行时间较短的代码时必不可少。
    • @Kragen - 这就是我对底层计时器的意思。我将通过参考 Win32 API 来澄清。
    • 请注意,它是Stopwatch 而不是StopWatch(我知道,这是次要的,但如果你弄错了,自动解析依赖项将不起作用)。
    【解决方案3】:

    使用下面的代码

    DateTime dExecutionTime;
    dExecutionTime = DateTime.Now;
          TimeSpan span = DateTime.Now.Subtract(dExecutionTime);
                      lblExecutinTime.Text = "total time taken " +   Math.Round(span.TotalMinutes,2) + " minutes .   >>---> " + DateTime.Now.ToShortTimeString();
    

    【讨论】:

      【解决方案4】:

      两者都不会影响性能,因为您说这并不重要。秒表似乎更合适 - 您只是从时间中减去时间,而不是从另一个日期中减去一个日期。日期的东西需要更多的内存和 CPU 时间来处理。如果您计划在多个地方重用它,还有一些方法可以使代码更清晰。想到重载using。我会搜索一个例子。好的,代码被盗:

      http://stevesmithblog.com/blog/great-uses-of-using-statement-in-c/

      public class ConsoleAutoStopWatch : IDisposable
      {
          private readonly Stopwatch _stopWatch;
      
          public ConsoleAutoStopWatch()
          {
              _stopWatch = new Stopwatch();
              _stopWatch.Start();
          }
      
          public void Dispose()
          {
              _stopWatch.Stop();
              TimeSpan ts = _stopWatch.Elapsed;
      
              string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
                                                 ts.Hours, ts.Minutes, ts.Seconds,
                                                 ts.Milliseconds / 10);
              Console.WriteLine(elapsedTime, "RunTime");
          }
      }
      
      private static void UsingStopWatchUsage()
      {
          Console.WriteLine("ConsoleAutoStopWatch Used: ");
          using (new ConsoleAutoStopWatch())
          {
              Thread.Sleep(3000);
          }
      }
      

      【讨论】:

      • 我认为不需要更多时间。我认为它不太准确,因为它不是为这种测量而设计的。
      【解决方案5】:

      我有一个小班来临时做这种事情。它使用秒表类 - c# micro perfomance testing

      例如。

      var tester = new PerformanceTester(() => SomeMethod());
      tester.MeasureExecTime(1000);
      Console.Writeline(string.Format("Executed in {0} milliseconds", tester.AverageTime.TotalMilliseconds));
      

      【讨论】:

        【解决方案6】:

        不仅StopWatch更准确,而且DateTime.Now在某些情况下会给出不正确的结果。

        考虑在夏令时切换期间会发生什么,例如 - 使用 DateTime.Now 实际上可以给出否定答案!

        【讨论】:

          【解决方案7】:

          两者都可能很好地满足您的需求,但我会说使用StopWatch。为什么?因为它适用于您正在执行的任务。

          你有一个类是为返回当前日期/时间而构建的,它恰好可以用于计时,你有一个专门为计时而设计的类。

          在这种情况下,只有在您需要毫秒精度时才真正存在差异(在这种情况下,StopWatch 更准确),但作为一般原则,如果存在专门用于您正在寻找的任务的工具,那么它会更好一个可以使用。

          【讨论】:

            【解决方案8】:

            这种情况我一般用StopWatch

            来自MSDN页面:

            秒表

            提供一组方法和 您可以使用的属性 准确测量经过的时间。

            在下面的帖子中,我用它来比较 LINQ 和 PLINQ 的执行时间:

            Parallel LINQ (PLINQ) with Visual Studio 2010

            【讨论】:

            • +1 链接到 MSDN,我发现名称似乎已从 StopWatch 更改为 Stopwatch
            猜你喜欢
            • 1970-01-01
            • 2013-03-21
            • 2016-06-15
            • 2022-01-03
            • 2023-03-09
            • 2015-07-25
            相关资源
            最近更新 更多