【问题标题】:How do I measure how long a function is running?如何测量函数运行的时间?
【发布时间】:2012-04-23 19:53:42
【问题描述】:

我想看看一个函数运行了多长时间。所以我在我的表单上添加了一个计时器对象,我得到了这段代码:

private int counter = 0;

// Inside button click I have:
timer = new Timer();
timer.Tick += new EventHandler(timer_Tick);
timer.Start();
Result result = new Result();
result = new GeneticAlgorithms().TabuSearch(parametersTabu, functia);
timer.Stop();

还有:

private void timer_Tick(object sender, EventArgs e)
{
    counter++;
    btnTabuSearch.Text = counter.ToString();
}

但这不算什么。为什么?

【问题讨论】:

标签: c# .net performance timer stopwatch


【解决方案1】:

为了在调试代码时查看断点之间经过的毫秒数,Visual Studio 提供了PerfTips,这是一个内置、有用且快速的工具。

【讨论】:

    【解决方案2】:

    Visual Studio 2015, 2017 Professional 和 Enterprise 有诊断工具。如果您在函数的末尾有一个断点,它将在 Events 选项卡下显示时间和持续时间,如图所示:

    您可以查看文章Diagnostic Tools debugger window in Visual Studio 2015了解更多详情。

    PS;到目前为止只有 Xamarin 形式,跨平台项目不支持此功能。我希望 Microsoft 也为 xamarin 表单项目带来这一强大功能。

    【讨论】:

    • 这已经很久了
    【解决方案3】:

    记录当前步骤开始处理的时间

    DateTime dtStart = DateTime.Now;
    
    //Calculate the total number of milliseconds request took (Timespan = to represent the time interval)-> current - started time stamp ...
    //TotalMilliseconds -->Gets the value of the current TimeSpan structure expressed in whole and fractional milliseconds.
    // to measure how long a function is running 
    var result=((TimeSpan)(DateTime.Now - dtStart)).TotalMilliseconds.ToString("#,##0.00") + "ms";
    

    【讨论】:

      【解决方案4】:

      您应该将秒表类用于计时功能。

      尝试以下方法:

      private int counter = 0;
      
      // setup stopwatch and begin timing
      var timer = System.Diagnostics.Stopwatch.StartNew();
      
      Result result = new Result();
      result = new GeneticAlgorithms().TabuSearch(parametersTabu, functia);
      
      // stop timer and get elapsed time
      timer.Stop();
      var elapsed = timer.Elapsed;
      
      // display result time
      MessageBox.Show(elapsed.ToString("mm':'ss':'fff"));
      

      【讨论】:

        【解决方案5】:

        我查看并同意所有建议。但是想分享一个执行时间记录器的通用实现,我们不想多次实现秒表逻辑,但仍想测量多个方法的执行时间。

        不以通用方式实现记录器的主要原因是 - 方法执行在 stopwatch.Start() 和 stopwatch.Stop() 之间,我们可能需要执行后的方法结果以进行进一步处理。

        因此,为了解决这个问题,我创建了以下示例实现,其中单独记录执行时间,而不将其与实际方法流混合。

        public static class Helper
        {
            public static T Time<T>(Func<T> method, ILogger log)
            {
                var stopwatch = new Stopwatch();
                stopwatch.Start();
                var result = method();
                stopwatch.Stop();
                log.Info(string.Format("Time Taken For Execution is:{0}", stopwatch.Elapsed.TotalMilliseconds));
                return result;
            }
        }
        
        public class Arithmatic
        {
            private ILogger _log;
            public Arithmatic(ILogger log)//Inject Dependency
            {
                _log = log;
            }
        
            public void Calculate(int a, int b)
            {
                try
                {
                    Console.WriteLine(Helper.Time(() => AddNumber(a, b), _log));//Return the result and do execution time logging
                    Console.WriteLine(Helper.Time(() => SubtractNumber(a, b), _log));//Return the result and do execution time logging
                }
                catch (Exception ex)
                {
                    _log.Error(ex.Message, ex);
                }
            }
        
            private string AddNumber(int a, int b)
            {
                return "Sum is:" + (a + b);
            }
        
            private string SubtractNumber(int a, int b)
            {
                return "Subtraction is:" + (a - b);
            }
        }
        
        public class Log : ILogger
        {
            public void Info(string message)
            {
                Console.WriteLine(message);
            }
        
            public void Error(string message, Exception ex)
            {
                Console.WriteLine("Error Message:" + message, "Stacktrace:" + ex.StackTrace);
            }
        }
        
        public interface ILogger
        {
            void Info(string message);
            void Error(string message, Exception ex);
        }
        

        调用部分:

         static void Main()
         {
            ILogger log = new Log();
            Arithmatic obj = new Arithmatic(log);
            obj.Calculate(10, 3);
            Console.ReadLine();
         }
        

        【讨论】:

        • 有趣的想法。感谢发帖。
        • 你不觉得代码包含太多无关信息吗,我相信只有helper方法和一行使用就足够了
        • 有些扩展我同意,但如果一个人想在更广泛/企业级别使用这个概念,那么他必须考虑所有这些信息,比如记录器和所有这些信息。所以我只是提到了详细的实现方式。
        【解决方案6】:

        使用 System.Diagnostics 的Stopwatch

        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);
        }
        

        【讨论】:

        • ts.ToString("hh:mm:ss.ff")ts.ToString("G")打印时间不是更方便吗?
        【解决方案7】:

        也许,你可以写一个这样的方法:

        public static void Time(Action action)
        {
            Stopwatch st = new Stopwatch();
            st.Start();
            action();
            st.Stop();
            Trace.WriteLine("Duration:" + st.Elapsed.ToString("mm\\:ss\\.ff"));
        }
        

        然后像这样使用它:

        Time(()=>
        {
         CallOfTheMethodIWantToMeasure();
        });
        

        【讨论】:

          【解决方案8】:

          为避免将来出现计时器问题,下面是正确的代码:

          timer = new Timer();
          timer.Tick += new EventHandler(timer_Tick);
          timer.Interval = 1; //set interval on 1 milliseconds
          timer.Enabled = true; //start the timer
          Result result = new Result();
          result = new GeneticAlgorithms().TabuSearch(parametersTabu, functia);
          timer.Enabled = false; //stop the timer
          

          private void timer_Tick(object sender, EventArgs e)
          {
             counter++;
             btnTabuSearch.Text = counter.ToString();
          }
          

          但这是错误的方法。您必须使用 Stopwatch (System.Diagnostic) 类,因为它是一个高分辨率计时器,而 Diagnostic 这个词说明了一切。

          所以试试这个:

          Stopwatch timer = Stopwatch.StartNew();
          
          Result result = new Result();
          result = new GeneticAlgorithms().TabuSearch(parametersTabu, functia);
          
          timer.Stop();  
          TimeSpan timespan = timer.Elapsed;
          
          btnTabuSearch.Text = String.Format("{0:00}:{1:00}:{2:00}", timespan.Minutes, timespan.Seconds, timespan.Milliseconds / 10);
          

          【讨论】:

          • 注意:将定时器设置为1ms的间隔,你应该注意不要认为你的计数器实际上是毫秒数。根据硬件,计时器(在我的计算机上)的最小间隔约为 15 毫秒。因此,即使您将间隔设置为 1 毫秒,它也只会每 15 毫秒左右触发一次。
          • 我明天试试计时器。我只是想要一个计数器来查看我按下按钮后经过了多少时间。
          • var timer = Stopwatch.StartNew();
          • 答案不正确。 Timer() 代码不再起作用。
          【解决方案9】:

          对于一个函数的计时,你应该使用Stopwatch Class

          另外,您的计时器不计数的原因是您没有为其设置时间间隔。

          【讨论】:

            【解决方案10】:

            不要使用计时器 - 使用 Stopwatch 类。

            var sw = new Stopwatch();
            Result result = new Result();
            
            sw.Start();
            result = new GeneticAlgorithms().TabuSearch(parametersTabu, functia);
            
            sw.Stop();
            
            // sw.Elapsed tells you how much time passed
            

            【讨论】:

            • 甚至var sw = Stopwatch.StartNew();
            【解决方案11】:

            查看一段代码需要多长时间运行的最佳方法是使用System.Diagnostics.Stopwatch

            这是一个例子:

            using System.Diagnostics;
            
            #if DEBUG
                 Stopwatch timer = new Stopwatch();
                 timer.Start();
            #endif
            
                 //Long running code
            
            #if DEBUG
                 timer.Stop();
                 Debug.WriteLine("Time Taken: " + timer.Elapsed.TotalMilliseconds.ToString("#,##0.00 'milliseconds'"));
            #endif
            

            我使用#if DEBUG 来确保秒表代码不会进入生产版本,但您可以不用它。

            【讨论】:

              猜你喜欢
              • 2021-12-28
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2012-08-15
              • 2014-10-21
              • 1970-01-01
              • 2020-07-08
              • 2010-09-23
              相关资源
              最近更新 更多