【问题标题】:How to use StopWatch multiple times in C#?如何在 C# 中多次使用 StopWatch?
【发布时间】:2018-12-12 11:20:23
【问题描述】:

我有执行不同操作的简短代码,我想测量执行每个操作所需的时间。我在这里阅读了有关秒表课程的信息,并想优化我的时间测量。 我的函数调用了 5 个其他函数,我想在不声明的情况下测量每个函数:

stopwatch sw1 = new stopwatch();
stopwatch sw2 = new stopwatch();
etc..

我的函数是这样的:

public bool func()
{
 ....
 func1()
 func2()
 ....
 ....
 func5()
}

有没有办法使用一个秒表实例来测量时间?

谢谢!!

【问题讨论】:

    标签: c# optimization time


    【解决方案1】:

    使用委托将方法作为参数传递给函数。

    这里我使用了 Action Delegates,因为指定的方法没有返回值。

    如果您的方法具有返回类型或参数,您可以使用函数委托

    进行相应修改
        static void Main(string[] args)
        {
            Console.WriteLine("Method 1 Time Elapsed (ms): {0}", TimeMethod(Method1));
            Console.WriteLine("Method 2 Time Elapsed (ms): {0}", TimeMethod(Method2));
        }
    
        static long TimeMethod(Action methodToTime)
        {
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            methodToTime();
            stopwatch.Stop();
            return stopwatch.ElapsedMilliseconds;
        }
    
        static void Method1()
        {
            for (int i = 0; i < 100000; i++)
            {
                for (int j = 0; j < 1000; j++)
                {
                }
            }
        }
    
        static void Method2()
        {
            for (int i = 0; i < 5000; i++)
            {
            }
        }
    }
    

    通过使用它,你可以传递任何你想要的方法。

    希望有帮助!

    【讨论】:

      【解决方案2】:

      你需要的是 Stopwatch 类的 Restart 函数,如下所示:

      public bool func()
      {
          var stopwatch = Stopwatch.StartNew();
      
          func1();
      
          Debug.WriteLine(stopwatch.ElapsedMilliseconds);
      
          stopwatch.Restart();
      
          func5();
      
          Debug.WriteLine(stopwatch.ElapsedMilliseconds);
      }
      

      【讨论】:

        【解决方案3】:

        是的,试试这个:

            void func1()
            {
                Stopwatch sw = new Stopwatch();
                sw.Start();
                func1();
                sw.Stop();
                Console.Write(sw.Elapsed);
        
                sw.Restart();
                func2();
                sw.Stop();
                Console.Write(sw.Elapsed);
            }
        

        【讨论】:

        • 这种情况下写sw.Restart和sw.Start有区别吗?
        • 使用 Restart 停止当前间隔测量并开始新的间隔测量 (MSDN)。重新启动将清除经过的时间。
        【解决方案4】:

        你可以使用这个小类:

        public class PolyStopwatch
        {
            readonly Dictionary<string, long> counters;
        
            readonly Stopwatch stopwatch;
        
            string currentLabel;
        
            public PolyStopwatch()
            {
                stopwatch = new Stopwatch();
                counters = new Dictionary<string, long>();
            }
        
            public void Start(string label)
            {
                if (currentLabel != null) Stop();
        
                currentLabel = label;
                if (!counters.ContainsKey(label))
                    counters.Add(label, 0);
                stopwatch.Restart();
            }
        
            public void Stop()
            {
                if (currentLabel == null)
                    throw new InvalidOperationException("No counter started");
        
                stopwatch.Stop();
                counters[currentLabel] += stopwatch.ElapsedMilliseconds;
                currentLabel = null;
            }
        
            public void Print()
            {
                if (currentLabel != null) Stop();
        
                long totalTime = counters.Values.Sum();
                foreach (KeyValuePair<string, long> kvp in counters)
                    Debug.Print("{0,-40}: {1,8:N0} ms ({2:P})", kvp.Key, kvp.Value, (double) kvp.Value / totalTime);
                Debug.WriteLine(new string('-', 62));
                Debug.Print("{0,-40}: {1,8:N0} ms", "Total time", totalTime);
            }
        }
        

        像这样使用它:

        var ps = new PolyStopwatch();
        
        ps.Start("Method1");
        Method1();
        ps.Stop();
        
        // other code...
        
        ps.Start("Method2");
        Method2();
        ps.Stop();
        
        ps.Print();
        

        如果调用相互跟随,您可以省略 Stop()

        ps.Start("Method1");
        Method1();
        ps.Start("Method2");
        Method2();
        ps.Print();
        

        它适用于循环:

        for(int i = 0; i < 10000; i++)
        {
            ps.Start("Method1");
            Method1();
            ps.Start("Method2");
            Method2();
        }
        ps.Print();
        

        【讨论】:

          【解决方案5】:

          我用:

          void MyFunc()
              {
                  Watcher watcher = new Watcher();
                  //Some call
                  HightLoadFunc();
                  watcher.Tick("My high load tick 1");
          
                  SecondFunc();
                  watcher.Tick("Second tick");
          
                  Debug.WriteLine(watcher.Result());
                  //Total: 0.8343141s; My high load tick 1: 0.4168064s; Second tick: 0.0010215s;
              }
          

          class Watcher
          {
              DateTime start;
              DateTime endTime;
          
              List<KeyValuePair<DateTime, string>> times = new List<KeyValuePair<DateTime, string>>();
          
              public Watcher()
              {
                  start = DateTime.Now;
                  times.Add(new KeyValuePair<DateTime, string>(start, "start"));
                  endTime = start;
              }
          
              public void Tick(string message)
              {
                  times.Add(new KeyValuePair<DateTime, string>(DateTime.Now, message));
              }
          
              public void End()
              {
                  endTime = DateTime.Now;
              }
          
              public string Result(bool useNewLine = false)
              {
                  string result = "";
                  if (endTime == start)
                      endTime = DateTime.Now;
          
                  var total = (endTime - start).TotalSeconds;
                  result = $"Total: {total}s;";
          
                  if (times.Count <2)
                      return result + " Not another times.";
                  else 
                      for(int i=1; i<times.Count; i++)
                      {
                          if (useNewLine) result += Environment.NewLine;
                          var time = (times[i].Key - times[i - 1].Key).TotalSeconds;
                          var m = times[i];
                          result += $" {m.Value}: {time}s;";
                      }
          
                  return result;
              }
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-01-18
            • 2013-02-14
            • 1970-01-01
            • 2016-06-10
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多