diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs index f75b019efe612..85b1658895f54 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs @@ -1448,10 +1448,10 @@ private void ExecuteAndCatchIfThrows_NoLock(DiagnosticAnalyzer analyzer, A { _cancellationToken.ThrowIfCancellationRequested(); - PooledStopwatch timer = null; + SharedStopwatch timer = default; if (_analyzerExecutionTimeMapOpt != null) { - timer = PooledStopwatch.StartInstance(); + timer = SharedStopwatch.StartNew(); // This call to Restart isn't required by the API, but is included to avoid measurement errors which // can occur during periods of high allocation activity. In some cases, calls to Stopwatch @@ -1468,12 +1468,11 @@ private void ExecuteAndCatchIfThrows_NoLock(DiagnosticAnalyzer analyzer, A analyze(argument); - if (timer != null) + if (_analyzerExecutionTimeMapOpt != null) { - timer.Stop(); + var elapsed = timer.Elapsed.Ticks; StrongBox totalTicks = _analyzerExecutionTimeMapOpt.GetOrAdd(analyzer, _ => new StrongBox(0)); - Interlocked.Add(ref totalTicks.Value, timer.Elapsed.Ticks); - timer.Free(); + Interlocked.Add(ref totalTicks.Value, elapsed); } } catch (Exception e) when (ExceptionFilter(e)) diff --git a/src/Compilers/Core/Portable/InternalUtilities/SharedStopwatch.cs b/src/Compilers/Core/Portable/InternalUtilities/SharedStopwatch.cs new file mode 100644 index 0000000000000..af862c08955d7 --- /dev/null +++ b/src/Compilers/Core/Portable/InternalUtilities/SharedStopwatch.cs @@ -0,0 +1,67 @@ +// 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. + +using System; +using System.Diagnostics; + +namespace Roslyn.Utilities +{ + internal struct SharedStopwatch + { + private static readonly Stopwatch s_stopwatch = Stopwatch.StartNew(); + + private TimeSpan _accumulated; + private TimeSpan _started; + + public readonly TimeSpan Elapsed + { + get + { + if (IsRunning) + return _accumulated + s_stopwatch.Elapsed - _started; + + return _accumulated; + } + } + + public readonly long ElapsedMilliseconds => (long)Elapsed.TotalMilliseconds; + public readonly bool IsRunning => _started != TimeSpan.Zero; + + public static SharedStopwatch StartNew() + { + var result = new SharedStopwatch(); + result.Start(); + return result; + } + + public void Reset() + { + Stop(); + _accumulated = TimeSpan.Zero; + } + + public void Restart() + { + Reset(); + Start(); + } + + public void Start() + { + if (!IsRunning) + { + _started = s_stopwatch.Elapsed; + } + } + + public void Stop() + { + if (IsRunning) + { + _accumulated += s_stopwatch.Elapsed - _started; + _started = TimeSpan.Zero; + } + } + } +} diff --git a/src/Dependencies/PooledObjects/Microsoft.CodeAnalysis.PooledObjects.projitems b/src/Dependencies/PooledObjects/Microsoft.CodeAnalysis.PooledObjects.projitems index 48f150a955713..13eaee66873fc 100644 --- a/src/Dependencies/PooledObjects/Microsoft.CodeAnalysis.PooledObjects.projitems +++ b/src/Dependencies/PooledObjects/Microsoft.CodeAnalysis.PooledObjects.projitems @@ -15,7 +15,6 @@ - \ No newline at end of file diff --git a/src/Dependencies/PooledObjects/PooledStopwatch.cs b/src/Dependencies/PooledObjects/PooledStopwatch.cs deleted file mode 100644 index 15fe84796d380..0000000000000 --- a/src/Dependencies/PooledObjects/PooledStopwatch.cs +++ /dev/null @@ -1,41 +0,0 @@ -// 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. - -using System; -using System.Diagnostics; - -namespace Microsoft.CodeAnalysis.PooledObjects -{ - internal class PooledStopwatch : Stopwatch - { - private static readonly ObjectPool s_poolInstance = CreatePool(); - - private readonly ObjectPool _pool; - - private PooledStopwatch(ObjectPool pool) - { - _pool = pool; - } - - public void Free() - { - Reset(); - _pool?.Free(this); - } - - public static ObjectPool CreatePool() - { - ObjectPool pool = null; - pool = new ObjectPool(() => new PooledStopwatch(pool), 128); - return pool; - } - - public static PooledStopwatch StartInstance() - { - var instance = s_poolInstance.Allocate(); - instance.Restart(); - return instance; - } - } -} diff --git a/src/Workspaces/Core/Portable/Microsoft.CodeAnalysis.Workspaces.csproj b/src/Workspaces/Core/Portable/Microsoft.CodeAnalysis.Workspaces.csproj index 524bc035d673b..06c554c4babbc 100644 --- a/src/Workspaces/Core/Portable/Microsoft.CodeAnalysis.Workspaces.csproj +++ b/src/Workspaces/Core/Portable/Microsoft.CodeAnalysis.Workspaces.csproj @@ -27,6 +27,7 @@ + Execution\Desktop\DesktopAnalyzerAssemblyLoader.cs