The Labs \ Source Viewer \ SSCLI \ System.Diagnostics \ Stopwatch

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. /*============================================================
  16. **
  17. ** Class:  Stopwatch
  18. **
  19. ** Purpose: Implementation for Stopwatch class.
  20. **
  21. ** Date:  Nov 27, 2002
  22. **
  23. ===========================================================*/
  24. namespace System.Diagnostics
  25. {
  26.     using Microsoft.Win32;
  27.     using System;
  28.    
  29.     // This class uses high-resolution performance counter if installed hardware
  30.     // does not support it. Otherwise, the class will fall back to DateTime class
  31.     // and uses ticks as a measurement.
  32.    
  33.     public class Stopwatch
  34.     {
  35.         private const long TicksPerMillisecond = 10000;
  36.         private const long TicksPerSecond = TicksPerMillisecond * 1000;
  37.        
  38.         private long elapsed;
  39.         private long startTimeStamp;
  40.         private bool isRunning;
  41.        
  42.         // "Frequency" stores the frequency of the high-resolution performance counter,
  43.         // if one exists. Otherwise it will store TicksPerSecond.
  44.         // The frequency cannot change while the system is running,
  45.         // so we only need to initialize it once.
  46.         public static readonly long Frequency;
  47.         public static readonly bool IsHighResolution;
  48.        
  49.         // performance-counter frequency, in counts per ticks.
  50.         // This can speed up conversion from high frequency performance-counter
  51.         // to ticks.
  52.         private static readonly double tickFrequency;
  53.        
  54.         static Stopwatch()
  55.         {
  56.             bool succeeded = SafeNativeMethods.QueryPerformanceFrequency(out Frequency);
  57.             if (!succeeded) {
  58.                 IsHighResolution = false;
  59.                 Frequency = TicksPerSecond;
  60.                 tickFrequency = 1;
  61.             }
  62.             else {
  63.                 IsHighResolution = true;
  64.                 tickFrequency = TicksPerSecond;
  65.                 tickFrequency /= Frequency;
  66.             }
  67.         }
  68.        
  69.         public Stopwatch()
  70.         {
  71.             Reset();
  72.         }
  73.        
  74.         public void Start()
  75.         {
  76.             // Calling start on a running Stopwatch is a no-op.
  77.             if (!isRunning) {
  78.                 startTimeStamp = GetTimestamp();
  79.                 isRunning = true;
  80.             }
  81.         }
  82.        
  83.         public static Stopwatch StartNew()
  84.         {
  85.             Stopwatch s = new Stopwatch();
  86.             s.Start();
  87.             return s;
  88.         }
  89.        
  90.         public void Stop()
  91.         {
  92.             // Calling stop on a stopped Stopwatch is a no-op.
  93.             if (isRunning) {
  94.                 long endTimeStamp = GetTimestamp();
  95.                 long elapsedThisPeriod = endTimeStamp - startTimeStamp;
  96.                 elapsed += elapsedThisPeriod;
  97.                 isRunning = false;
  98.             }
  99.         }
  100.        
  101.         public void Reset()
  102.         {
  103.             elapsed = 0;
  104.             isRunning = false;
  105.             startTimeStamp = 0;
  106.         }
  107.        
  108.         public bool IsRunning {
  109.             get { return isRunning; }
  110.         }
  111.        
  112.         public TimeSpan Elapsed {
  113.             get { return new TimeSpan(GetElapsedDateTimeTicks()); }
  114.         }
  115.        
  116.         public long ElapsedMilliseconds {
  117.             get { return GetElapsedDateTimeTicks() / TicksPerMillisecond; }
  118.         }
  119.        
  120.         public long ElapsedTicks {
  121.             get { return GetRawElapsedTicks(); }
  122.         }
  123.        
  124.         public static long GetTimestamp()
  125.         {
  126.             if (IsHighResolution) {
  127.                 long timestamp = 0;
  128.                 SafeNativeMethods.QueryPerformanceCounter(out timestamp);
  129.                 return timestamp;
  130.             }
  131.             else {
  132.                 return DateTime.UtcNow.Ticks;
  133.             }
  134.         }
  135.        
  136.         // Get the elapsed ticks.
  137.         private long GetRawElapsedTicks()
  138.         {
  139.             long timeElapsed = elapsed;
  140.            
  141.             if (isRunning) {
  142.                 // If the StopWatch is running, add elapsed time since
  143.                 // the Stopwatch is started last time.
  144.                 long currentTimeStamp = GetTimestamp();
  145.                 long elapsedUntilNow = currentTimeStamp - startTimeStamp;
  146.                 timeElapsed += elapsedUntilNow;
  147.             }
  148.             return timeElapsed;
  149.         }
  150.        
  151.         // Get the elapsed ticks.
  152.         private long GetElapsedDateTimeTicks()
  153.         {
  154.             long rawTicks = GetRawElapsedTicks();
  155.             if (IsHighResolution) {
  156.                 // convert high resolution perf counter to DateTime ticks
  157.                 double dticks = rawTicks;
  158.                 dticks *= tickFrequency;
  159.                 return unchecked((long)dticks);
  160.             }
  161.             else {
  162.                 return rawTicks;
  163.             }
  164.         }
  165.        
  166.     }
  167. }

Developer Fusion