diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs index f75b019efe612c0be3ffc0206a194f71f8d1ff89..85b1658895f54dbde2b465b2a9bdfba64136ceda 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 0000000000000000000000000000000000000000..af862c08955d71882ee9fb94e8f6136087c77f2a --- /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 48f150a9557134c16135dd87e09aa55a31db59e5..13eaee66873fcd405d206d52c0c78c4815f71194 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 15fe84796d3801a5a85b67e50c25176f7e7ee292..0000000000000000000000000000000000000000 --- 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 524bc035d673b65816ad642d83dd98999dc1fb5c..06c554c4babbc109b96c4d028e856a75328f4ad7 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