使用.NET 2.0中的秒表-Stopwatch类进行速度测试

    软件的运行速度必须要在用户可以接受的范围内。通常,改善那些短暂的但频繁使用的例程的速度会大幅度地提高软件的整体速度。
    要改善速度,当然首先要能够量度时间。好,那我们考虑一下在跑道上的情况,枪声一响,马上按下秒表开始计时,在选手到达终点那一刻结束计时,这时就可以知道该选手所用的时间了。要开始对下一轮比赛计时前,要先将秒表归零。.NET2.0也提供了这样一个秒表:Stopwatch类,它可以比较精确地测量时间。

    速度测试:
    软件的性能和可测性是一个复杂的主题。要确保应用程序能够满足用户的期望,就需要在开发周期内考虑它的性能和可测性。这在设计阶段至关重要,一个糟糕的设计几乎肯定会导致糟糕的用户体验。然而,仅仅有好的设计也不能保证程序能够高效地运行,最终代码的质量同样重要。
    量度一个运行时间较长的例程相当简单。如果一个过程会持续几分钟,只要一块腕表就可以记录它的时间了。比如一个执行时间为两分钟的过程,10%的改善能够节省12秒,这是很容易去确定的。
    而如果要测量一个非常短暂的过程,就要考虑更好的精确性了。比如有一些很小的例程,它们的运行时间可能只有千分之一秒,但会被调用100万次,这样的累积效果就明显了。在.NET framework的先前版本中,需要使用Windows API函数,而在.NET framework 2.0中,微软引入了Stopwatch(它就是我们的秒表)类来简化时间的量度任务。
    Stopwatch类:
    使用Stopwatch类来量度时间非常简单。跟现实生活中的秒表一样,这个类的对象也能够对计数器进行开始、停止、归零(重置)操作,不过它可比一般的秒表精确多了,它能够精确到微秒(也就是百万分之一秒)。
    示例代码:
    要演示Stopwatch的使用还是来段代码吧。下面是一个控制台应用程序,它将1到100万之间的所有整数累加:

    using System;

    
namespace StopWatchClass
    {
        
class Program
        {
            
static void Main(string[] args)
            {
                long total = 0;

                
for (int i = 1; i <= 10000000; i++)
                {
                    total 
+= i;
                }
            }
        }
    }
   
    添加Stopwatch对象:
    Stopwatch类位于System.Diagnostics命名空间。下面是添加对象后的代码:
    using System;
    
using System.Diagnostics;

    
namespace StopWatchClass
    {
        
class Program
        {
            
static void Main(string[] args)
            {
                Stopwatch timer 
new Stopwatch();
                
long total = 0;

                
for (int i = 1; i <= 10000000; i++)
                {
                    total 
+= i;
                }
            }
        }
    }

    控制Stopwatch对象:
    Stopwatch提供了几个方法用以控制Stopwatch对象。Start方法开始一个计时操作,Stop方法停止计时。此时如果第二次使用Start方法,将继续计时,最终的计时结果为两次计时的累加。为避免这种情况,在第二次计时前用Reset方法将对象归零。这三个方法都不需要参数。代码是:
    using System;
    
using System.Diagnostics;

    
namespace StopWatchClass
    {
        
class Program
        {
            
static void Main(string[] args)
            {
                Stopwatch timer 
= new Stopwatch();
                
long total = 0;

                timer.Start();
                
for (int i = 1; i <= 10000000; i++)
                {
                    total 
+= i;
                }

                timer.Stop();

            }
        }
    }

    读取Stopwatch结果:
    在结束计时后下一步就是读取计时结果了。Stopwatch类提供了以下属性:
  1. Elapsed:返回一个TimeSpan对象,表示计时时间间隔;
  2. ElapsedMilliseconds:返回计时经过的微秒数,精确度稍差,适合于稍长一点的计时;
  3. ElapsedTicks:返回计时经过的计时器刻度(timer tick)数。计时器刻度是Stopwatch对象可能的最小量度单位。计时器刻度时间的长度由特定的计算机和操作系统确定。Stopwatch对象的Frequency静态字段的值表示一秒所包含的计时器刻度数。注意它与TimeSpan的Ticks属性所用的时间单位的区别。

        应当根据计时任务的情况选择其中的一个属性。在我们的示例程序中,Elapsed属性提供了需要的精确度,用它来输出经过的微秒数。这也是TimeSpan的最高精确度了。
        下面是最终的程序代码:

        using System;
        
    using System.Diagnostics;

        
    namespace StopWatchClass
        {
            
    class Program
            {
                
    static void Main(string[] args)
                {
                    Stopwatch timer 
    = new Stopwatch();
                    
    long total = 0;

                    timer.Start();
                    
    for (int i = 1; i <= 10000000; i++)
                    {
                        total 
    += i;
                    }

                    timer.Stop();

                    
    decimal micro = timer.Elapsed.Ticks / 10m;
                    Console.WriteLine(
    "Execution time was {0:F1} microseconds.", micro);
                }
            }
        }

        另外,使用IsRunning属性可以查看一个Stopwatch实例是否正在计时,使用StartNew方法可以开始一个新的计时器。


        参考:http://www.blackwasp.co.uk/SpeedTestWithStopwatch.aspx

     


    posted @ 2006-12-17 18:25 Anders Cui 阅读(2285) 评论(7)  编辑 收藏 所属分类: 02-Winows Forms00-.NET Framework

      回复  引用  查看    
    #1楼 2006-12-17 19:03 | Cat Chen      
    “它能够精确到微秒(也就是百万分之一秒)”——这是DateTime和TimeSpan的最高精度,还是确定说Stopwatch的测量真能够精确到这精度?
      回复  引用  查看    
    #2楼 [楼主]2006-12-17 19:23 | Anders Cui      
    Stopwatch的精度由Frequency决定
    而Frequency字段则由特定的计算机和操作系统确定
    比如我的机器是3579545
    那么在我的机器上Stopwatch能精确到3579545分之1秒
    所以它也能精确到微秒
      回复  引用  查看    
    #3楼 [楼主]2006-12-17 19:35 | Anders Cui      
    DateTime和TimeSpan也是一样
    精度受系统定时器的时钟频率(也就是Stopwatch的Frequency属性)所限

    http://saftsack.fs.uni-bayreuth.de/~dun3/archives/more-accurate-timing-stopwatch-performancetimer-queryperformancecounter/19.html
    这篇文章或许能够揭示Stopwatch的实现以及它与Windows API的关系
      回复  引用  查看    
    #4楼 2006-12-17 23:55 | kwklover      
    Stopwatch
    Community Server就有一个自己写的

    Stopwatch不定要用在测试代码性能方面.用途很多啊

    我看Community Server Enterprise Search项目就用这个类.用来控制DotLucene做索引的时候,控制做索引的时间.

      回复  引用  查看    
    #5楼 [楼主]2006-12-18 09:21 | Anders Cui      
    @kwklover
    对,用途很多,很多关于计时的任务都可以用它
    我这里只是一方面的应用:)
      回复  引用  查看    
    #6楼 2007-03-15 21:07 | 玉开      
    需要注意的是,即使使用了Stopwatch类,也不能在debug模式下面测试程序运行的性能,这样做的误差非常大。

    我吃过一次亏,所以提示一下,也许多此一举,呵呵。
      回复  引用  查看    
    #7楼 [楼主]2007-03-15 21:11 | Anders Cui      
    @玉开
    多谢了

    今天看到你的随笔了
    关于for和foreach的
    我们是该精益求精的,呵呵

    标题  
    姓名  
    主页
    Email (只有博主才能看到) 
    验证码 *  看不清,换一张 [登录][注册]
    内容(请不要发表任何与政治相关的内容)  
      登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
    该文被作者在 2006-12-25 19:48 编辑过


    相关链接: