65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 LogTimer 测量时间

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.38/5 (6投票s)

2012年3月6日

CPOL

3分钟阅读

viewsIcon

24528

downloadIcon

368

如何使用 LogTimer 测量时间并找出应用程序的瓶颈点。

引言

在我上一个项目中,我需要检查是什么减慢了我的应用程序的速度。为了找出行为异常的应用程序的瓶颈,我需要测量几个代码块的执行时间。

虽然 System.Diagnostics.StopWatch 是这个问题的显而易见的解决方案,但它缺少我想要的一些功能

  • 测量样本 - 样本是 Start() 及其顺序 Stop() 之间的间隔。
  • 检索最后一个样本的持续时间 - 虽然 System.Diagnostics.StopWatch 允许测量所有样本的持续时间(所有 StartStop 间隔的持续时间),但你不能检索最后一个样本的持续时间(最后一个 Start 及其顺序 Stop 间隔)。
  • 检索总执行时间 - 总执行时间可能有以下含义之一
    • 自第一个 Start() 和最后一个 Stop() 以来经过的时间
    • 自第一个 Start() 和当前时间以来经过的时间
  • 从总执行时间中检索测量的样本时间百分比
  • 检索样本的数量(StartStop 间隔)并查询样本的平均执行时间。

演示程序

演示程序演示了如何使用 LogTimer。我们将测量 DoSomeWork(int timeout) 的执行时间,它只是休眠 timeout 毫秒。计时器数据将在每一步之后显示在控制台上,时间显示为毫秒数。
public class LogTimerDemo {
  //-------------------------------------------------------------------------
  public static void Main(string[] args) {
    LogTimerDemo demo = new LogTimerDemo();
    LogTimer timer = new LogTimer();

    demo.Display(timer,"0");
    //-----------------------------------------------------------------------
    // Stage 1 : Let measure the exectution time of DoSomeWork(2000)
    timer.Start(); demo.DoSomeWork(2000); timer.Stop();
    demo.Display(timer,"1");
    //-----------------------------------------------------------------------
    // Stage 2 - Let wait 3 seconds. Note the influence of AllFromNow property
    Thread.Sleep(3000);
    timer.AllFromNow = false; demo.Display(timer,"2");
    timer.AllFromNow = true;  demo.Display(timer,"3");
    //-----------------------------------------------------------------------
    // Stage 4 : Let measure the exectution time of DoSomeWork(5000)
    timer.Start(); demo.DoSomeWork(5000); timer.Stop();
    demo.Display(timer,"4");
    //-----------------------------------------------------------------------
    // Stage 4 : Let measure the exectution's time of calling DoSomeWork(100)
    // 100 times in sequence and check the average time DoSomeWork(100). Note
    // that we use AddSample() that is more accurate than calling Stop() and
    // Start() in sequence.
    timer.Reset();
    for (int ii = 0;ii > 100;ii++) {
      timer.AddSample();
      demo.DoSomeWork(100);
    }
    timer.Stop();
    demo.Display(timer,"5");
    //-----------------------------------------------------------------------
  }
  //-------------------------------------------------------------------------
  public void DoSomeWork(int ms) {
    Thread.Sleep(ms);
  }
  //-------------------------------------------------------------------------
  public void Display(LogTimer timer,string perfix) {
    System.Console.WriteLine("{6} => All: {0:D5} , Value: {1:D5} , Current: {2:D5}, Stats: {3,3}%, Average ; {4:D5} [{5} samples]",timer.All.Ms(),timer.Value.Ms(),timer.Current.Ms(),timer.PercentAll,timer.Average.Ms(),timer.Count,perfix);
  }
  //-------------------------------------------------------------------------
}

这是程序在我机器上的输出

使用 LogTimer

  • 你可以通过调用 Start() 来启动一个新样本(开始测量时间)。你也可以在创建新计时器时立即启动计时器,方法是用 true 调用构造函数。虽然允许在计时器运行时(测量时间)调用 Start(),但计时器将忽略它。
  • 你可以通过调用 Stop() 来结束样本(停止测量时间)。此函数的返回值是最后一个样本的时间(自上次有效 Start() 以来测量的时间)。此样本的时间也会添加到总测量时间中。计时器停止后,你可以调用 Start() 以在以后的时间测量其他事件。虽然允许在计时器未运行时(测量时间)调用 Stop(),但计时器将忽略它。
  • 你可以通过调用 AddSample 来添加新样本。这与按顺序调用 Stop()Start 的效果相同,但它更准确。
  • 你可以通过调用 Reset() 来重置计时器。如果使用 true 调用,或者通过调用 Restart(),你也可以立即启动计时器。
  • 你可以使用 Value 属性来检索总测量时间(所有样本的时间)。如果在计时器运行时调用该属性,则该值将是在属性调用时测量的时间。
  • 你可以使用 Current 属性来检索最后一个样本的时间(最后一个 Start()Stop() 之间的间隔)。如果在计时器运行时调用该属性,则该值将是在属性调用时测量的时间。
  • 你可以使用 All 属性来检索总执行时间。此测量的实际含义取决于 AllFromNow 属性的值。如果该属性为 true,则该值将是自上次 Reset() 后第一次调用 Start() 和当前时间之间经过的时间,否则该值将是自上次 Reset() 后第一次调用 Start() 和最后一次调用 Stop() 之间经过的时间。如果在计时器运行时调用该属性,则该值将是在属性调用时测量的时间。
  • 你可以使用 Count 属性来检索 Start()Stop() 间隔的数量。Average 属性是间隔的平均持续时间。(Value/Count

历史

  • 版本 3 - 添加 AllFromNowRestart
  • 版本 2 - 解释了 System.Diagnostics.StopWatchLogTimer 之间的区别。
  • 版本 1
© . All rights reserved.