diff --git a/src/Features/Core/Portable/Diagnostics/DiagnosticAnalyzerService_UpdateSource.cs b/src/Features/Core/Portable/Diagnostics/DiagnosticAnalyzerService_UpdateSource.cs
index b742e336d8ce412b0aecd434e1e9522d636e1399..3f74ec02dd8af0c2d197d7b4e8402dc345874ae1 100644
--- a/src/Features/Core/Portable/Diagnostics/DiagnosticAnalyzerService_UpdateSource.cs
+++ b/src/Features/Core/Portable/Diagnostics/DiagnosticAnalyzerService_UpdateSource.cs
@@ -20,7 +20,10 @@ internal partial class DiagnosticAnalyzerService : IDiagnosticUpdateSource
private DiagnosticAnalyzerService(IDiagnosticUpdateSourceRegistrationService registrationService) : this()
{
_eventMap = new EventMap();
- _eventQueue = new SimpleTaskQueue(TaskScheduler.Default);
+
+ // use diagnostic event task scheduler so that we never flood async events queue with million of events.
+ // queue itself can handle huge number of events but we are seeing OOM due to captured data in pending events.
+ _eventQueue = new SimpleTaskQueue(new DiagnosticEventTaskScheduler(blockingUpperBound: 100));
registrationService.Register(this);
}
diff --git a/src/Features/Core/Portable/Diagnostics/DiagnosticEventTaskScheduler.cs b/src/Features/Core/Portable/Diagnostics/DiagnosticEventTaskScheduler.cs
new file mode 100644
index 0000000000000000000000000000000000000000..a79d647a01ccf45d2aa34bae31a4a0126ac733e3
--- /dev/null
+++ b/src/Features/Core/Portable/Diagnostics/DiagnosticEventTaskScheduler.cs
@@ -0,0 +1,55 @@
+// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+using Roslyn.Utilities;
+
+namespace Microsoft.CodeAnalysis.Diagnostics
+{
+ ///
+ /// This task scheduler will block queuing new tasks if upper bound has met.
+ ///
+ internal class DiagnosticEventTaskScheduler : TaskScheduler
+ {
+ private readonly Task _mainTask;
+ private readonly BlockingCollection _tasks;
+
+ public DiagnosticEventTaskScheduler(int blockingUpperBound)
+ {
+ _tasks = new BlockingCollection(blockingUpperBound);
+
+ // portable layer doesnt support explicit thread creation. use long running task to create and hold onto a thread
+ _mainTask = Task.Factory.SafeStartNew(Start, CancellationToken.None,
+ TaskCreationOptions.DenyChildAttach | TaskCreationOptions.LongRunning, TaskScheduler.Default);
+ }
+
+ private void Start()
+ {
+ while (true)
+ {
+ var task = _tasks.Take();
+ bool ret = this.TryExecuteTask(task);
+ }
+ }
+
+ protected override void QueueTask(Task task)
+ {
+ _tasks.Add(task);
+ }
+
+ protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
+ {
+ // NOTE: TPL will ensure only one task ever run when running scheduled task. and since this is only used
+ // in diagnostic events, we know task will ever run sequencely. so no worry about reverted order here.
+ return this.TryExecuteTask(task);
+ }
+
+ protected override IEnumerable GetScheduledTasks()
+ {
+ // debugger will use this method to get scheduled tasks for this scheduler
+ return _tasks.ToArray();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Features/Core/Portable/Diagnostics/DiagnosticService.cs b/src/Features/Core/Portable/Diagnostics/DiagnosticService.cs
index 3dbbe6624e46c1058c5dd1bcfd8ebb18b90b1f2c..ab368dc658ac4e1fdf51d250f85b5e63eec9df63 100644
--- a/src/Features/Core/Portable/Diagnostics/DiagnosticService.cs
+++ b/src/Features/Core/Portable/Diagnostics/DiagnosticService.cs
@@ -30,7 +30,10 @@ public DiagnosticService([ImportMany] IEnumerable
+ /// Only For Testing
+ ///
+ internal string Name_TestingOnly
{
get { return _stateName; }
}
- internal string Language
+ ///
+ /// Only For Testing
+ ///
+ internal string Language_TestingOnly
{
get { return _language; }
}
diff --git a/src/Features/Core/Portable/Diagnostics/EngineV1/DiagnosticIncrementalAnalyzer.StateManager.cs b/src/Features/Core/Portable/Diagnostics/EngineV1/DiagnosticIncrementalAnalyzer.StateManager.cs
index 85de338c1516131ef65624afd77c261aba644ef7..2865384195cb98a7ae71a55dbda87c7f1042aad4 100644
--- a/src/Features/Core/Portable/Diagnostics/EngineV1/DiagnosticIncrementalAnalyzer.StateManager.cs
+++ b/src/Features/Core/Portable/Diagnostics/EngineV1/DiagnosticIncrementalAnalyzer.StateManager.cs
@@ -178,7 +178,7 @@ private static void VerifyDiagnosticStates(IEnumerable stateSets)
{
var state = stateSet.GetState((StateType)i);
- if (!(set.Add(ValueTuple.Create(state.Language, state.Name))))
+ if (!(set.Add(ValueTuple.Create(state.Language_TestingOnly, state.Name_TestingOnly))))
{
Contract.Fail();
}
diff --git a/src/Features/Core/Portable/Diagnostics/EngineV1/DiagnosticIncrementalAnalyzer.cs b/src/Features/Core/Portable/Diagnostics/EngineV1/DiagnosticIncrementalAnalyzer.cs
index 7613d0335687cdb1b24f9aaae95bf89f5a85577e..438ec74813ca96bc52c5ba8c6485dedad3955db2 100644
--- a/src/Features/Core/Portable/Diagnostics/EngineV1/DiagnosticIncrementalAnalyzer.cs
+++ b/src/Features/Core/Portable/Diagnostics/EngineV1/DiagnosticIncrementalAnalyzer.cs
@@ -181,7 +181,7 @@ private async Task AnalyzeSyntaxAsync(Document document, ImmutableHashSet.Empty, data.Items);
continue;
}
@@ -617,6 +617,11 @@ private static bool CheckSemanticVersions(Project project, AnalysisData existing
project.CanReusePersistedDependentSemanticVersion(versions.ProjectVersion, versions.DataVersion, existingData.DataVersion);
}
+ private void RaiseDiagnosticCreatedFromCacheIfNeeded(StateType type, Document document, StateSet stateSet, ImmutableArray items)
+ {
+ RaiseDocumentDiagnosticsUpdatedIfNeeded(type, document, stateSet, ImmutableArray.Empty, items);
+ }
+
private void RaiseDocumentDiagnosticsUpdatedIfNeeded(
StateType type, Document document, StateSet stateSet, ImmutableArray existingItems, ImmutableArray newItems)
{
diff --git a/src/Features/Core/Portable/Features.csproj b/src/Features/Core/Portable/Features.csproj
index a8d1522d17cdf8da9aec968c6db61833c25db811..3cfcc45b0a98c3342511c97a085a3302b9ee1d7b 100644
--- a/src/Features/Core/Portable/Features.csproj
+++ b/src/Features/Core/Portable/Features.csproj
@@ -177,6 +177,7 @@
+