计时 (System.Diagnostics.Stopwatch, DateTime)

创建时间:
2016-03-28 10:20
最近更新:
2018-08-13 01:56

时间的单位

1 秒 =             1,000 毫秒 (ms)
1 秒 =         1,000,000 微秒 (μs)
1 秒 =     1,000,000,000 纳秒 (ns)
1 秒 = 1,000,000,000,000 皮秒 (ps)

1 毫秒 = 1/            1,000 秒 (s)
1 微秒 = 1/        1,000,000 秒 (s)
1 纳秒 = 1/    1,000,000,000 秒 (s)
1 皮秒 = 1/1,000,000,000,000 秒 (s)

Resource

  1. 一个简单的性能计数器: CodeTimer

Resource - MSDN

  1. Stopwatch 类 - 提供一组方法和属性,可用于准确地测量运行时间。

Stopwatch 类 测试记录

Test by Tony on 2016-03-28.

using System;
using System.Diagnostics;
using System.Threading;
class Program
{
    static void Main(string[] args)
    {
        //获取以每秒计时周期数表示的计时器频率。
        long frequency = Stopwatch.Frequency; //3117928
        //指示计时器是否基于高分辨率性能计数器。
        bool isHighResolution = Stopwatch.IsHighResolution; //true
        //获取计时器机制中的当前最小时间单位数。
        long timestamp = Stopwatch.GetTimestamp(); //861711402986

        var sw = new Stopwatch();
        //开始或继续测量某个时间间隔的运行时间。
        sw.Start();
        Thread.Sleep(3000);
        //停止测量某个时间间隔的运行时间。
        sw.Stop();
        //获取当前实例测量得出的总运行时间。
        TimeSpan ts = sw.Elapsed; //{00:00:03.0002213}
        //获取当前实例测量得出的总运行时间(以毫秒为单位)。
        long ms = sw.ElapsedMilliseconds; //3000
        //获取当前实例测量得出的总运行时间(用计时器计时周期表示)。
        long ticks = sw.ElapsedTicks; //9354558

        string elapsedTime = String.Format(
            "{0:00}:{1:00}:{2:00}.{3:00}",
            ts.Hours,
            ts.Minutes,
            ts.Seconds,
            ts.Milliseconds / 10
        ); //"00:00:03.00"
        Console.WriteLine("RunTime " + elapsedTime);
    }
}

常用代码片段

var sw = new Stopwatch();
sw.Start();
//some code
sw.Stop();
double elapsed = sw.Elapsed.TotalMilliseconds;  //有小数,更精确
//double elapsed = sw.ElapsedMilliseconds;        //无小数

测量消耗的时间 (基于 DateTime 的实现)

Test by Tony on 2016-03-28.

using System;
using System.Threading;

namespace Net451Console
{
    class Program
    {
        static void Main(string[] args)
        {
            DateTime begin = DateTime.Now;
            int millisecondsTimeout = 3000;
            Thread.Sleep(millisecondsTimeout);
            DateTime end = DateTime.Now;
            TimeSpan elapse = end - begin;
            double seconds = elapse.TotalSeconds; //获取以整秒数和秒的小数部分表示的当前 System.TimeSpan 结构的值。
            double milliseconds = elapse.TotalMilliseconds; //获取以整毫秒数和毫秒的小数部分表示的当前 System.TimeSpan 结构的值。
            Console.WriteLine(seconds);
            Console.WriteLine(milliseconds);
            Console.ReadKey(true);
        }
    }
}

Source Code of System.Diagnostics.Stopwatch from JetBrains dotPeek 1.0 at 2017-12-02

Complete Copy:

// Type: System.Diagnostics.Stopwatch
// Assembly: System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
// Assembly location: C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.dll

using Microsoft.Win32;
using System;

namespace System.Diagnostics
{
  [__DynamicallyInvokable]
  public class Stopwatch
  {
    private const long TicksPerMillisecond = 10000L;
    private const long TicksPerSecond = 10000000L;
    private long elapsed;
    private long startTimeStamp;
    private bool isRunning;
    [__DynamicallyInvokable]
    public static readonly long Frequency;
    [__DynamicallyInvokable]
    public static readonly bool IsHighResolution;
    private static readonly double tickFrequency;

    [__DynamicallyInvokable]
    public bool IsRunning
    {
      [__DynamicallyInvokable] get
      {
        return this.isRunning;
      }
    }

    [__DynamicallyInvokable]
    public TimeSpan Elapsed
    {
      [__DynamicallyInvokable] get
      {
        return new TimeSpan(this.GetElapsedDateTimeTicks());
      }
    }

    [__DynamicallyInvokable]
    public long ElapsedMilliseconds
    {
      [__DynamicallyInvokable] get
      {
        return this.GetElapsedDateTimeTicks() / 10000L;
      }
    }

    [__DynamicallyInvokable]
    public long ElapsedTicks
    {
      [__DynamicallyInvokable] get
      {
        return this.GetRawElapsedTicks();
      }
    }

    static Stopwatch()
    {
      if (!SafeNativeMethods.QueryPerformanceFrequency(out Stopwatch.Frequency))
      {
        Stopwatch.IsHighResolution = false;
        Stopwatch.Frequency = 10000000L;
        Stopwatch.tickFrequency = 1.0;
      }
      else
      {
        Stopwatch.IsHighResolution = true;
        Stopwatch.tickFrequency = 10000000.0;
        Stopwatch.tickFrequency /= (double) Stopwatch.Frequency;
      }
    }

    [__DynamicallyInvokable]
    public Stopwatch()
    {
      this.Reset();
    }

    [__DynamicallyInvokable]
    public void Start()
    {
      if (this.isRunning)
        return;
      this.startTimeStamp = Stopwatch.GetTimestamp();
      this.isRunning = true;
    }

    [__DynamicallyInvokable]
    public static Stopwatch StartNew()
    {
      Stopwatch stopwatch = new Stopwatch();
      stopwatch.Start();
      return stopwatch;
    }

    [__DynamicallyInvokable]
    public void Stop()
    {
      if (!this.isRunning)
        return;
      this.elapsed = this.elapsed + (Stopwatch.GetTimestamp() - this.startTimeStamp);
      this.isRunning = false;
      if (this.elapsed >= 0L)
        return;
      this.elapsed = 0L;
    }

    [__DynamicallyInvokable]
    public void Reset()
    {
      this.elapsed = 0L;
      this.isRunning = false;
      this.startTimeStamp = 0L;
    }

    [__DynamicallyInvokable]
    public void Restart()
    {
      this.elapsed = 0L;
      this.startTimeStamp = Stopwatch.GetTimestamp();
      this.isRunning = true;
    }

    [__DynamicallyInvokable]
    public static long GetTimestamp()
    {
      if (!Stopwatch.IsHighResolution)
        return DateTime.UtcNow.Ticks;
      long num = 0L;
      SafeNativeMethods.QueryPerformanceCounter(out num);
      return num;
    }

    private long GetRawElapsedTicks()
    {
      long num1 = this.elapsed;
      if (this.isRunning)
      {
        long num2 = Stopwatch.GetTimestamp() - this.startTimeStamp;
        num1 += num2;
      }
      return num1;
    }

    private long GetElapsedDateTimeTicks()
    {
      long rawElapsedTicks = this.GetRawElapsedTicks();
      if (Stopwatch.IsHighResolution)
        return (long) ((double) rawElapsedTicks * Stopwatch.tickFrequency);
      else
        return rawElapsedTicks;
    }
  }
}