From 6fd07e47457587cf2679e597d90b372d1f4a6e3e Mon Sep 17 00:00:00 2001 From: Vladimir Sadov Date: Thu, 24 Oct 2019 05:23:17 -0700 Subject: [PATCH] Moving StopWatch to `src\Common\src\Corelib` (dotnet/corefx#42072) Signed-off-by: dotnet-bot --- .../shared/System/Diagnostics/Stopwatch.Unix.cs | 19 +++ .../shared/System/Diagnostics/Stopwatch.Windows.cs | 31 +++++ .../shared/System/Diagnostics/Stopwatch.cs | 142 +++++++++++++++++++++ 3 files changed, 192 insertions(+) create mode 100644 netcore/System.Private.CoreLib/shared/System/Diagnostics/Stopwatch.Unix.cs create mode 100644 netcore/System.Private.CoreLib/shared/System/Diagnostics/Stopwatch.Windows.cs create mode 100644 netcore/System.Private.CoreLib/shared/System/Diagnostics/Stopwatch.cs diff --git a/netcore/System.Private.CoreLib/shared/System/Diagnostics/Stopwatch.Unix.cs b/netcore/System.Private.CoreLib/shared/System/Diagnostics/Stopwatch.Unix.cs new file mode 100644 index 00000000000..13beddde046 --- /dev/null +++ b/netcore/System.Private.CoreLib/shared/System/Diagnostics/Stopwatch.Unix.cs @@ -0,0 +1,19 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Diagnostics +{ + public partial class Stopwatch + { + private static long QueryPerformanceFrequency() + { + return (long)Interop.Sys.GetTimestampResolution(); + } + + private static long QueryPerformanceCounter() + { + return (long)Interop.Sys.GetTimestamp(); + } + } +} diff --git a/netcore/System.Private.CoreLib/shared/System/Diagnostics/Stopwatch.Windows.cs b/netcore/System.Private.CoreLib/shared/System/Diagnostics/Stopwatch.Windows.cs new file mode 100644 index 00000000000..20f5656cbf1 --- /dev/null +++ b/netcore/System.Private.CoreLib/shared/System/Diagnostics/Stopwatch.Windows.cs @@ -0,0 +1,31 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Diagnostics +{ + public partial class Stopwatch + { + private static unsafe long QueryPerformanceFrequency() + { + long resolution; + + Interop.BOOL result = Interop.Kernel32.QueryPerformanceFrequency(&resolution); + // The P/Invoke is documented to never fail on Windows XP or later + Debug.Assert(result != Interop.BOOL.FALSE); + + return resolution; + } + + private static unsafe long QueryPerformanceCounter() + { + long timestamp; + + Interop.BOOL result = Interop.Kernel32.QueryPerformanceCounter(×tamp); + // The P/Invoke is documented to never fail on Windows XP or later + Debug.Assert(result != Interop.BOOL.FALSE); + + return timestamp; + } + } +} diff --git a/netcore/System.Private.CoreLib/shared/System/Diagnostics/Stopwatch.cs b/netcore/System.Private.CoreLib/shared/System/Diagnostics/Stopwatch.cs new file mode 100644 index 00000000000..3b7c0bac5c9 --- /dev/null +++ b/netcore/System.Private.CoreLib/shared/System/Diagnostics/Stopwatch.cs @@ -0,0 +1,142 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Diagnostics +{ + // This class uses high-resolution performance counter if the installed + // hardware supports it. Otherwise, the class will fall back to DateTime + // and uses ticks as a measurement. + + public partial class Stopwatch + { + private const long TicksPerMillisecond = 10000; + private const long TicksPerSecond = TicksPerMillisecond * 1000; + + private long _elapsed; + private long _startTimeStamp; + private bool _isRunning; + + // "Frequency" stores the frequency of the high-resolution performance counter, + // if one exists. Otherwise it will store TicksPerSecond. + // The frequency cannot change while the system is running, + // so we only need to initialize it once. + public static readonly long Frequency = QueryPerformanceFrequency(); + public static readonly bool IsHighResolution = true; + + // performance-counter frequency, in counts per ticks. + // This can speed up conversion from high frequency performance-counter + // to ticks. + private static readonly double s_tickFrequency = (double)TicksPerSecond / Frequency; + + public Stopwatch() + { + Reset(); + } + + public void Start() + { + // Calling start on a running Stopwatch is a no-op. + if (!_isRunning) + { + _startTimeStamp = GetTimestamp(); + _isRunning = true; + } + } + + public static Stopwatch StartNew() + { + Stopwatch s = new Stopwatch(); + s.Start(); + return s; + } + + public void Stop() + { + // Calling stop on a stopped Stopwatch is a no-op. + if (_isRunning) + { + long endTimeStamp = GetTimestamp(); + long elapsedThisPeriod = endTimeStamp - _startTimeStamp; + _elapsed += elapsedThisPeriod; + _isRunning = false; + + if (_elapsed < 0) + { + // When measuring small time periods the Stopwatch.Elapsed* + // properties can return negative values. This is due to + // bugs in the basic input/output system (BIOS) or the hardware + // abstraction layer (HAL) on machines with variable-speed CPUs + // (e.g. Intel SpeedStep). + + _elapsed = 0; + } + } + } + + public void Reset() + { + _elapsed = 0; + _isRunning = false; + _startTimeStamp = 0; + } + + // Convenience method for replacing {sw.Reset(); sw.Start();} with a single sw.Restart() + public void Restart() + { + _elapsed = 0; + _startTimeStamp = GetTimestamp(); + _isRunning = true; + } + + public bool IsRunning + { + get { return _isRunning; } + } + + public TimeSpan Elapsed + { + get { return new TimeSpan(GetElapsedDateTimeTicks()); } + } + + public long ElapsedMilliseconds + { + get { return GetElapsedDateTimeTicks() / TicksPerMillisecond; } + } + + public long ElapsedTicks + { + get { return GetRawElapsedTicks(); } + } + + public static long GetTimestamp() + { + Debug.Assert(IsHighResolution); + return QueryPerformanceCounter(); + } + + // Get the elapsed ticks. + private long GetRawElapsedTicks() + { + long timeElapsed = _elapsed; + + if (_isRunning) + { + // If the Stopwatch is running, add elapsed time since + // the Stopwatch is started last time. + long currentTimeStamp = GetTimestamp(); + long elapsedUntilNow = currentTimeStamp - _startTimeStamp; + timeElapsed += elapsedUntilNow; + } + return timeElapsed; + } + + // Get the elapsed ticks. + private long GetElapsedDateTimeTicks() + { + Debug.Assert(IsHighResolution); + // convert high resolution perf counter to DateTime ticks + return unchecked((long)(GetRawElapsedTicks() * s_tickFrequency)); + } + } +} -- 2.11.4.GIT