【问题标题】:Calculate the execution time of a method计算方法的执行时间
【发布时间】:2012-12-10 18:25:09
【问题描述】:

可能重复:
How do I measure how long a function is running?

我有一个 I/O 计时方法,可以将数据从一个位置复制到另一个位置。计算执行时间的最佳和最真实的方法是什么? Thread? Timer? Stopwatch?还有其他解决方案吗?我想要最准确的,并且尽可能简短。

【问题讨论】:

    标签: c# .net timer io stopwatch


    【解决方案1】:

    Stopwatch 就是为此目的而设计的,它是在 .NET 中衡量时间执行的最佳方法之一。

    var watch = System.Diagnostics.Stopwatch.StartNew();
    // the code that you want to measure comes here
    watch.Stop();
    var elapsedMs = watch.ElapsedMilliseconds;
    

    Do not use DateTime 测量 .NET 中的执行时间。


    更新:

    正如@series0ne 在 cmets 部分中指出的那样:如果您想要对某些代码的执行进行真正精确的测量,您将不得不使用操作系统中内置的性能计数器。 following answer 包含一个很好的概述。

    【讨论】:

    • 没错,这种情况呢:我有一个 foreach 循环,里面有一个 ThreadPool.QueueUserWorkItem(delegate { CopyFiles(folder, dest); }); ,但是秒表在一切完成之前就停止了。
    • @DarinDimitrov - 秒表不完全准确?请记住,.NET 背景噪音(例如 JITing)会导致执行时间发生变化。因此,实际上,为了准确测量,OP 应该使用性能分析器。
    • @series0ne,非常好的观点。我会更新我的答案以包含您的宝贵意见。
    • @DarinDimitrov,我最近采访了一位非常熟练的高级开发人员。他向我指出,使用 DateTimes 实际上比使用 StopWatch 更准确。他说这样做的原因是.NET 中的 Stopwatch 没有考虑 CPU 亲和性,因此,如果您的线程从一个内核移动到另一个内核,则 StopWatch 不会考虑跨其他内核的执行时间;只有线程开始执行的那个。您对此有何看法?
    • @series0ne,高级开发人员告诉你的关于秒表和日期时间的内容是绝对正确的。除了 DateTime 你没有足够的准确性。问题是 .NET 中没有这样的类可以为您提供所有这些功能。
    【解决方案2】:

    根据个人经验,System.Diagnostics.Stopwatch 类可以用来衡量方法的执行时间,但是,注意:它并不完全准确!

    考虑以下示例:

    Stopwatch sw;
    
    for(int index = 0; index < 10; index++)
    {
        sw = Stopwatch.StartNew();
        DoSomething();
        Console.WriteLine(sw.ElapsedMilliseconds);
    }
    
    sw.Stop();
    

    示例结果

    132ms
    4ms
    3ms
    3ms
    2ms
    3ms
    34ms
    2ms
    1ms
    1ms
    

    现在你想知道; “那么为什么第一次需要 132 毫秒,而其余时间明显更少?”

    答案是Stopwatch 不补偿 .NET 中的“背景噪音”活动,例如 JITing。因此,当您第一次运行您的方法时,首先要使用 .NET JIT。执行此操作所需的时间会添加到执行时间中。同样,其他因素也会导致执行时间发生变化。

    您真正应该寻找的绝对准确度是性能分析

    看看以下内容:

    RedGate ANTS Performance Profiler 是一种商业产品,但会产生非常准确的结果。 - Boost the performance of your applications with .NET profiling

    这是一篇关于分析的 StackOverflow 文章:-What Are Some Good .NET Profilers?

    我还写了一篇关于使用秒表进行性能分析的文章,您可能想看看 - Performance profiling in .NET

    【讨论】:

    • @mahditahsildari 没问题。很高兴我能帮助你! :-)
    • 我不知道为什么这是一个不准确的例子。秒表准确地测量了第一次调用的总成本,这肯定与将要运行此代码的客户相关。他们不关心这 132 毫秒是计入方法执行还是计入抖动,他们关心的是经过的总时间。
    • @series0ne 如果您关心循环的性能,请测量循环的性能。不要简单地假设做某事 n 次意味着它执行一次会慢 n 倍。
    • 首先,代码示例应生成数字不断增加的输出,因为 StopWatch 永远不会在循环中重置。 “应该”我的意思是它确实(我检查过)。所以你的输出与代码不匹配。其次,当我更正代码以在循环中执行停止/写入/重置/启动时,第一次测量与其余测量相同。我的猜测是你的 DoSomething 第一次运行的时间更长。 JIT 可能是也可能不是原因,但这并不是秒表影响测量。因此-1。
    • ILIA BROUDNO 绝对正确,我得到了相同的结果。 @series0ne,你在循环中有一个 Console.WriteLine,到目前为止写的是 ms;因为你只在循环结束后才停止手表,它会随着每次迭代而随着时间的推移而增加,所以我们应该看到像 3、6、10、12、15 ......随着时间在执行过程中的累积。
    【解决方案3】:

    StopWatch 类寻找您的最佳解决方案。

    Stopwatch sw = Stopwatch.StartNew();
    DoSomeWork();
    sw.Stop();
    
    Console.WriteLine("Time taken: {0}ms", sw.Elapsed.TotalMilliseconds);
    

    它还有一个名为Stopwatch.IsHighResolution 的静态字段。当然,这是硬件和操作系统的问题。

    指示计时器是否基于高分辨率性能 计数器。

    【讨论】:

      【解决方案4】:

      如果您有兴趣了解性能,最好的答案是使用分析器。

      否则,System.Diagnostics.StopWatch 提供高分辨率计时器。

      【讨论】:

      • 绝对正确!我有点沮丧,这里有这么多人建议使用秒表,因为它并不完全准确。但是,正如您建议使用性能分析器,这是正确的方法! +1
      【解决方案5】:

      StopWatch 将使用高分辨率计数器

      秒表通过在 底层定时器机制。如果安装的硬件和操作 系统支持高分辨率性能计数器,则 秒表类使用该计数器来测量经过的时间。否则, Stopwatch 类使用系统计时器来测量经过的时间。采用 用于确定精度的频率和 IsHighResolution 字段 秒表计时实现的解决方案。

      如果您正在测量 IO,那么您的数据可能会受到外部事件的影响,我会非常担心。 精确度(正如您在上面指出的那样)。相反,我会进行一系列测量并考虑这些数字的平均值和分布。

      【讨论】:

        【解决方案6】:

        关注这个Microsoft Doc:

        using System;
        using System.Diagnostics;
        using System.Threading;
        class Program
        {
            static void Main(string[] args)
            {
                Stopwatch stopWatch = new Stopwatch();
                stopWatch.Start();
                Thread.Sleep(10000);
                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("RunTime " + elapsedTime);
            }
        }
        

        输出: RunTime 00:00:09.94

        【讨论】:

          【解决方案7】:

          您也可以使用它,“获取自系统启动以来经过的毫秒数。”

          System.Environment.TickCount
          

          例如

          static void method1()
          {
              for (int i = 1; i <= 100; i++)
              {
                  Console.WriteLine("Test1 " + i);
              }
          }
          static void Main(string[] args)
          {
              var startTime = Environment.TickCount;
              method1();
              var endTime = Environment.TickCount;
              Console.WriteLine("RunTime " + (endTime - startTime));
          }
          

          【讨论】:

            【解决方案8】:
             using System.Diagnostics;
             class Program
             {
                static void Test1()
                {
                    for (int i = 1; i <= 100; i++)
                    {
                        Console.WriteLine("Test1 " + i);
                    }
                }
              static void Main(string[] args)
                {
            
                    Stopwatch sw = new Stopwatch();
                    sw.Start();
                    Test1();
                    sw.Stop();
                    Console.WriteLine("Time Taken-->{0}",sw.ElapsedMilliseconds);
               }
             }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2021-06-21
              • 1970-01-01
              • 1970-01-01
              • 2012-01-27
              • 2020-07-22
              • 2018-01-28
              • 1970-01-01
              • 2018-11-03
              相关资源
              最近更新 更多