diff --git a/src/VisualStudio/Core/Impl/Options/AbstractLocalUserRegistryOptionSerializer.cs b/src/VisualStudio/Core/Impl/Options/AbstractLocalUserRegistryOptionSerializer.cs
new file mode 100644
index 0000000000000..d17bf7db8ebd8
--- /dev/null
+++ b/src/VisualStudio/Core/Impl/Options/AbstractLocalUserRegistryOptionSerializer.cs
@@ -0,0 +1,96 @@
+// 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;
+using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
+using Microsoft.CodeAnalysis.Options;
+using Microsoft.CodeAnalysis.Options.Providers;
+using Microsoft.VisualStudio.Shell;
+using Microsoft.VisualStudio.Shell.Interop;
+using Microsoft.Win32;
+
+namespace Microsoft.VisualStudio.LanguageServices.Implementation.Options
+{
+ internal abstract class AbstractLocalUserRegistryOptionSerializer : ForegroundThreadAffinitizedObject, IOptionSerializer
+ {
+ ///
+ /// An object to gate access to .
+ ///
+ private readonly object _gate = new object();
+ private readonly RegistryKey _registryKey;
+
+ protected abstract string GetCollectionPathForOption(OptionKey key);
+
+ public AbstractLocalUserRegistryOptionSerializer(IServiceProvider serviceProvider)
+ : base(assertIsForeground: true) // The VSRegistry.RegistryRoot call requires being on the UI thread or else it will marshal and risk deadlock
+ {
+ this._registryKey = VSRegistry.RegistryRoot(serviceProvider, __VsLocalRegistryType.RegType_UserSettings, writable: true);
+ }
+
+ bool IOptionSerializer.TryFetch(OptionKey optionKey, out object value)
+ {
+ var collectionPath = GetCollectionPathForOption(optionKey);
+ if (collectionPath == null)
+ {
+ value = null;
+ return false;
+ }
+
+ lock (_gate)
+ {
+ using (var subKey = this._registryKey.OpenSubKey(collectionPath))
+ {
+ if (subKey == null)
+ {
+ value = null;
+ return false;
+ }
+
+ // Options that are of type bool have to be serialized as integers
+ if (optionKey.Option.Type == typeof(bool))
+ {
+ value = subKey.GetValue(optionKey.Option.Name, defaultValue: (bool)optionKey.Option.DefaultValue ? 1 : 0).Equals(1);
+ return true;
+ }
+ else
+ {
+ // Otherwise we can just store normally
+ value = subKey.GetValue(optionKey.Option.Name, defaultValue: optionKey.Option.DefaultValue);
+ return true;
+ }
+ }
+ }
+ }
+
+ bool IOptionSerializer.TryPersist(OptionKey optionKey, object value)
+ {
+ if (this._registryKey == null)
+ {
+ throw new InvalidOperationException();
+ }
+
+ var collectionPath = GetCollectionPathForOption(optionKey);
+ if (collectionPath == null)
+ {
+ return false;
+ }
+
+ lock (_gate)
+ {
+ using (var subKey = this._registryKey.CreateSubKey(collectionPath))
+ {
+ // Options that are of type bool have to be serialized as integers
+ if (optionKey.Option.Type == typeof(bool))
+ {
+ subKey.SetValue(optionKey.Option.Name, (bool)value ? 1 : 0, RegistryValueKind.DWord);
+ return true;
+ }
+ else
+ {
+ subKey.SetValue(optionKey.Option.Name, value);
+ return true;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/VisualStudio/Core/Impl/Options/AbstractSettingStoreOptionSerializer.cs b/src/VisualStudio/Core/Impl/Options/AbstractSettingStoreOptionSerializer.cs
deleted file mode 100644
index bcd282f6fe838..0000000000000
--- a/src/VisualStudio/Core/Impl/Options/AbstractSettingStoreOptionSerializer.cs
+++ /dev/null
@@ -1,93 +0,0 @@
-// 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;
-using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
-using Microsoft.CodeAnalysis.Options;
-using Microsoft.CodeAnalysis.Options.Providers;
-using Microsoft.VisualStudio.Shell;
-using Microsoft.VisualStudio.Shell.Interop;
-using Microsoft.Win32;
-
-namespace Microsoft.VisualStudio.LanguageServices.Implementation.Options
-{
- internal abstract class AbstractSettingStoreOptionSerializer : ForegroundThreadAffinitizedObject, IOptionSerializer
- {
- // The gate object guards the RegistryKey
- protected readonly object Gate = new object();
- protected readonly RegistryKey RegistryKey;
-
- protected abstract Tuple GetCollectionPathAndPropertyNameForOption(IOption key, string languageName);
-
- public AbstractSettingStoreOptionSerializer(IServiceProvider serviceProvider)
- : base(assertIsForeground: true) // The VSRegistry.RegistryRoot call requires being on the UI thread or else it will marshal and risk deadlock
- {
- this.RegistryKey = VSRegistry.RegistryRoot(serviceProvider, __VsLocalRegistryType.RegType_UserSettings, writable: true);
- }
-
- public virtual bool TryFetch(OptionKey optionKey, out object value)
- {
- return TryFetch(optionKey, (r, k, o) => r.GetValue(k, defaultValue: (bool)o.DefaultValue ? 1 : 0).Equals(1), out value);
- }
-
- public virtual bool TryPersist(OptionKey optionKey, object value)
- {
- return TryPersist(optionKey, value, (r, k, o, v) => r.SetValue(k, (bool)v ? 1 : 0, RegistryValueKind.DWord));
- }
-
- protected bool TryFetch(OptionKey optionKey, Func valueGetter, out object value)
- {
- if (this.RegistryKey == null)
- {
- throw new InvalidOperationException();
- }
-
- var collectionPathAndPropertyName = GetCollectionPathAndPropertyNameForOption(optionKey.Option, optionKey.Language);
- if (collectionPathAndPropertyName == null)
- {
- value = null;
- return false;
- }
-
- lock (Gate)
- {
- using (var subKey = this.RegistryKey.OpenSubKey(collectionPathAndPropertyName.Item1))
- {
- if (subKey == null)
- {
- value = null;
- return false;
- }
-
- value = valueGetter(subKey, collectionPathAndPropertyName.Item2, optionKey.Option);
- return true;
- }
- }
- }
-
- protected bool TryPersist(OptionKey optionKey, object value, Action valueSetter)
- {
- // We ignore languageName, since the current use of this class is only for
- // language-specific options that apply to a single language. The underlying option
- // service has already ensured the languageName is right, so we'll drop it on the floor.
- if (this.RegistryKey == null)
- {
- throw new InvalidOperationException();
- }
-
- var collectionPathAndPropertyName = GetCollectionPathAndPropertyNameForOption(optionKey.Option, optionKey.Language);
- if (collectionPathAndPropertyName == null)
- {
- return false;
- }
-
- lock (Gate)
- {
- using (var subKey = this.RegistryKey.CreateSubKey(collectionPathAndPropertyName.Item1))
- {
- valueSetter(subKey, collectionPathAndPropertyName.Item2, optionKey.Option, value);
- return true;
- }
- }
- }
- }
-}
diff --git a/src/VisualStudio/Core/Impl/Options/InternalOptionSerializer.cs b/src/VisualStudio/Core/Impl/Options/InternalOptionSerializer.cs
index 8124387957515..3e3821218c8f5 100644
--- a/src/VisualStudio/Core/Impl/Options/InternalOptionSerializer.cs
+++ b/src/VisualStudio/Core/Impl/Options/InternalOptionSerializer.cs
@@ -21,7 +21,7 @@ namespace Microsoft.VisualStudio.LanguageServices.Implementation.Options
CacheOptions.FeatureName,
InternalDiagnosticsOptions.OptionName,
InternalSolutionCrawlerOptions.OptionName), Shared]
- internal class InternalOptionSerializer : AbstractSettingStoreOptionSerializer
+ internal class InternalOptionSerializer : AbstractLocalUserRegistryOptionSerializer
{
[ImportingConstructor]
public InternalOptionSerializer(SVsServiceProvider serviceProvider)
@@ -29,62 +29,38 @@ public InternalOptionSerializer(SVsServiceProvider serviceProvider)
{
}
- protected override Tuple GetCollectionPathAndPropertyNameForOption(IOption key, string languageName)
+ protected override string GetCollectionPathForOption(OptionKey key)
{
- if (key.Feature == EditorComponentOnOffOptions.OptionName)
+ if (key.Option.Feature == EditorComponentOnOffOptions.OptionName)
{
- return Tuple.Create(@"Roslyn\Internal\OnOff\Components", key.Name);
+ return @"Roslyn\Internal\OnOff\Components";
}
- else if (key.Feature == InternalFeatureOnOffOptions.OptionName)
+ else if (key.Option.Feature == InternalFeatureOnOffOptions.OptionName)
{
- return Tuple.Create(@"Roslyn\Internal\OnOff\Features", key.Name);
+ return @"Roslyn\Internal\OnOff\Features";
}
- else if (key.Feature == PerformanceFunctionIdOptionsProvider.Name)
+ else if (key.Option.Feature == PerformanceFunctionIdOptionsProvider.Name)
{
- return Tuple.Create(@"Roslyn\Internal\Performance\FunctionId", key.Name);
+ return @"Roslyn\Internal\Performance\FunctionId";
}
- else if (key.Feature == LoggerOptions.FeatureName)
+ else if (key.Option.Feature == LoggerOptions.FeatureName)
{
- return Tuple.Create(@"Roslyn\Internal\Performance\Logger", key.Name);
+ return @"Roslyn\Internal\Performance\Logger";
}
- else if (key.Feature == InternalDiagnosticsOptions.OptionName)
+ else if (key.Option.Feature == InternalDiagnosticsOptions.OptionName)
{
- return Tuple.Create(@"Roslyn\Internal\Diagnostics", key.Name);
+ return @"Roslyn\Internal\Diagnostics";
}
- else if (key.Feature == InternalSolutionCrawlerOptions.OptionName)
+ else if (key.Option.Feature == InternalSolutionCrawlerOptions.OptionName)
{
- return Tuple.Create(@"Roslyn\Internal\SolutionCrawler", key.Name);
+ return @"Roslyn\Internal\SolutionCrawler";
}
- else if (key.Feature == CacheOptions.FeatureName)
+ else if (key.Option.Feature == CacheOptions.FeatureName)
{
- return Tuple.Create(@"Roslyn\Internal\Performance\Cache", key.Name);
+ return @"Roslyn\Internal\Performance\Cache";
}
throw ExceptionUtilities.Unreachable;
}
-
- public override bool TryFetch(OptionKey optionKey, out object value)
- {
- switch (optionKey.Option.Feature)
- {
- case CacheOptions.FeatureName:
- case InternalSolutionCrawlerOptions.OptionName:
- return TryFetch(optionKey, (r, k, o) => r.GetValue(k, defaultValue: o.DefaultValue), out value);
- }
-
- return base.TryFetch(optionKey, out value);
- }
-
- public override bool TryPersist(OptionKey optionKey, object value)
- {
- switch (optionKey.Option.Feature)
- {
- case CacheOptions.FeatureName:
- case InternalSolutionCrawlerOptions.OptionName:
- return TryPersist(optionKey, value, (r, k, o, v) => r.SetValue(k, v, o.Type == typeof(int) ? RegistryValueKind.DWord : RegistryValueKind.QWord));
- }
-
- return base.TryPersist(optionKey, value);
- }
}
}
diff --git a/src/VisualStudio/Core/Impl/ServicesVisualStudioImpl.csproj b/src/VisualStudio/Core/Impl/ServicesVisualStudioImpl.csproj
index 693794ed5db78..953a405263a60 100644
--- a/src/VisualStudio/Core/Impl/ServicesVisualStudioImpl.csproj
+++ b/src/VisualStudio/Core/Impl/ServicesVisualStudioImpl.csproj
@@ -244,7 +244,7 @@
-
+
diff --git a/src/VisualStudio/VisualStudioDiagnosticsToolWindow/OptionPages/ForceLowMemoryMode.cs b/src/VisualStudio/VisualStudioDiagnosticsToolWindow/OptionPages/ForceLowMemoryMode.cs
index 0819647e6177a..31f2cc86114b5 100644
--- a/src/VisualStudio/VisualStudioDiagnosticsToolWindow/OptionPages/ForceLowMemoryMode.cs
+++ b/src/VisualStudio/VisualStudioDiagnosticsToolWindow/OptionPages/ForceLowMemoryMode.cs
@@ -2,41 +2,48 @@
using System;
using System.Collections.Generic;
+using System.Threading;
using System.Threading.Tasks;
+using Microsoft.CodeAnalysis.Options;
namespace Roslyn.VisualStudio.DiagnosticsWindow.OptionsPages
{
- internal class ForceLowMemoryMode
+ internal sealed partial class ForceLowMemoryMode
{
+ private readonly IOptionService _optionService;
private MemoryHogger _hogger;
- public static readonly ForceLowMemoryMode Instance = new ForceLowMemoryMode();
-
- private ForceLowMemoryMode()
+ public ForceLowMemoryMode(IOptionService optionService)
{
+ _optionService = optionService;
+
+ optionService.OptionChanged += Options_OptionChanged;
+
+ RefreshFromSettings();
}
- public int Size { get; set; } = 500; // default to 500 MB
+ private void Options_OptionChanged(object sender, OptionChangedEventArgs e)
+ {
+ if (e.Option.Feature == ForceLowMemoryMode.OptionName)
+ {
+ RefreshFromSettings();
+ }
+ }
- public bool Enabled
+ private void RefreshFromSettings()
{
- get
+ var enabled = _optionService.GetOption(Enabled);
+
+ if (_hogger != null)
{
- return _hogger != null;
+ _hogger.Cancel();
+ _hogger = null;
}
- set
+ if (enabled)
{
- if (value && _hogger == null)
- {
- _hogger = new MemoryHogger();
- var ignore = _hogger.PopulateAndMonitorAsync(this.Size);
- }
- else if (!value && _hogger != null)
- {
- _hogger.Cancel();
- _hogger = null;
- }
+ _hogger = new MemoryHogger();
+ var ignore = _hogger.PopulateAndMonitorAsync(_optionService.GetOption(SizeInMegabytes));
}
}
@@ -46,7 +53,7 @@ private class MemoryHogger
private const int MonitorDelay = 10000; // 10 seconds
private readonly List _blocks = new List();
- private bool _cancelled;
+ private readonly CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource();
public MemoryHogger()
{
@@ -59,55 +66,35 @@ public int Count
public void Cancel()
{
- _cancelled = true;
+ _cancellationTokenSource.Cancel();
}
public Task PopulateAndMonitorAsync(int size)
{
// run on background thread
- return Task.Run(() => this.PopulateAndMonitorWorkerAsync(size));
+ return Task.Factory.StartNew(() => this.PopulateAndMonitorWorkerAsync(size), CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default).Unwrap();
}
private async Task PopulateAndMonitorWorkerAsync(int size)
{
try
- {
- for (int n = 0; n < size && !_cancelled; n++)
- {
- var block = new byte[BlockSize];
-
- // initialize block bits (so the memory actually gets allocated.. silly runtime!)
- for (int i = 0; i < BlockSize; i++)
- {
- block[i] = 0xFF;
- }
-
- _blocks.Add(block);
-
- // don't hog the thread
- await Task.Yield();
- }
- }
- catch (OutOfMemoryException)
- {
- }
-
- // monitor memory to keep it paged in
- while (!_cancelled)
{
try
{
- // access all block bytes
- for (var b = 0; b < _blocks.Count && !_cancelled; b++)
+ for (int n = 0; n < size; n++)
{
- var block = _blocks[b];
+ _cancellationTokenSource.Token.ThrowIfCancellationRequested();
- byte tmp;
- for (int i = 0; i < block.Length; i++)
+ var block = new byte[BlockSize];
+
+ // initialize block bits (so the memory actually gets allocated.. silly runtime!)
+ for (int i = 0; i < BlockSize; i++)
{
- tmp = block[i];
+ block[i] = 0xFF;
}
+ _blocks.Add(block);
+
// don't hog the thread
await Task.Yield();
}
@@ -116,16 +103,47 @@ private async Task PopulateAndMonitorWorkerAsync(int size)
{
}
- await Task.Delay(MonitorDelay).ConfigureAwait(true);
- }
+ // monitor memory to keep it paged in
+ while (true)
+ {
+ _cancellationTokenSource.Token.ThrowIfCancellationRequested();
+
+ try
+ {
+ // access all block bytes
+ for (var b = 0; b < _blocks.Count; b++)
+ {
+ _cancellationTokenSource.Token.ThrowIfCancellationRequested();
+
+ var block = _blocks[b];
- _blocks.Clear();
+ byte tmp;
+ for (int i = 0; i < block.Length; i++)
+ {
+ tmp = block[i];
+ }
- // force garbage collection
- for (int i = 0; i < 5; i++)
+ // don't hog the thread
+ await Task.Yield();
+ }
+ }
+ catch (OutOfMemoryException)
+ {
+ }
+
+ await Task.Delay(MonitorDelay, _cancellationTokenSource.Token).ConfigureAwait(false);
+ }
+ }
+ catch (OperationCanceledException)
{
- GC.Collect(GC.MaxGeneration);
- GC.WaitForPendingFinalizers();
+ _blocks.Clear();
+
+ // force garbage collection
+ for (int i = 0; i < 5; i++)
+ {
+ GC.Collect(GC.MaxGeneration);
+ GC.WaitForPendingFinalizers();
+ }
}
}
}
diff --git a/src/VisualStudio/VisualStudioDiagnosticsToolWindow/OptionPages/ForceLowMemoryMode_Options.cs b/src/VisualStudio/VisualStudioDiagnosticsToolWindow/OptionPages/ForceLowMemoryMode_Options.cs
new file mode 100644
index 0000000000000..2905a375d7108
--- /dev/null
+++ b/src/VisualStudio/VisualStudioDiagnosticsToolWindow/OptionPages/ForceLowMemoryMode_Options.cs
@@ -0,0 +1,31 @@
+// 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;
+using System.Composition;
+using Microsoft.CodeAnalysis.Options;
+using Microsoft.VisualStudio.LanguageServices.Implementation.Options;
+using Microsoft.VisualStudio.Shell;
+
+namespace Roslyn.VisualStudio.DiagnosticsWindow.OptionsPages
+{
+ internal sealed partial class ForceLowMemoryMode
+ {
+ public const string OptionName = nameof(ForceLowMemoryMode);
+ public static readonly Option Enabled = new Option(OptionName, nameof(Enabled), defaultValue: false);
+ public static readonly Option SizeInMegabytes = new Option(OptionName, nameof(SizeInMegabytes), defaultValue: 500);
+ }
+
+ [ExportOptionSerializer(ForceLowMemoryMode.OptionName), Shared]
+ internal sealed class ForceLowMemoryModeSerializer : AbstractLocalUserRegistryOptionSerializer
+ {
+ [ImportingConstructor]
+ public ForceLowMemoryModeSerializer(SVsServiceProvider serviceProvider) : base(serviceProvider)
+ {
+ }
+
+ protected override string GetCollectionPathForOption(OptionKey key)
+ {
+ return @"Roslyn\ForceLowMemoryMode";
+ }
+ }
+}
diff --git a/src/VisualStudio/VisualStudioDiagnosticsToolWindow/OptionPages/InternalFeaturesOnOffPage.cs b/src/VisualStudio/VisualStudioDiagnosticsToolWindow/OptionPages/InternalFeaturesOnOffPage.cs
index 5ed986e9cd107..26c14b8d2e454 100644
--- a/src/VisualStudio/VisualStudioDiagnosticsToolWindow/OptionPages/InternalFeaturesOnOffPage.cs
+++ b/src/VisualStudio/VisualStudioDiagnosticsToolWindow/OptionPages/InternalFeaturesOnOffPage.cs
@@ -35,48 +35,23 @@ public InternalFeaturesOptionsControl(string featureOptionName, IServiceProvider
protected override void AddOptions(Panel panel)
{
- base.AddOptions(panel);
-
// add force low memory mode option
var group = new WrapPanel();
- var lowMemoryMode = ForceLowMemoryMode.Instance;
- var cb = CreateBoundCheckBox("Forced Low Memory Mode", lowMemoryMode, "Enabled");
- group.Children.Add(cb);
- var tb = CreateBoundTextBox("", lowMemoryMode, "Size");
- group.Children.Add(tb);
- var text = new TextBlock() { Text = "MB" };
- group.Children.Add(text);
- panel.Children.Add(group);
- }
-
- private CheckBox CreateBoundCheckBox(string content, object source, string sourcePropertyName)
- {
- var cb = new CheckBox { Content = content };
- var binding = new Binding()
- {
- Source = source,
- Path = new PropertyPath(sourcePropertyName)
- };
-
- base.AddBinding(cb.SetBinding(CheckBox.IsCheckedProperty, binding));
+ var cb = new CheckBox { Content = "Forced Low Memory Mode: allocate" };
+ BindToOption(cb, ForceLowMemoryMode.Enabled);
+ group.Children.Add(cb);
- return cb;
- }
+ var textBox = new TextBox { MinWidth = 60 };
+ BindToOption(textBox, ForceLowMemoryMode.SizeInMegabytes);
+ group.Children.Add(textBox);
- private TextBox CreateBoundTextBox(string content, object source, string sourcePropertyName)
- {
- var tb = new TextBox { Text = content };
+ group.Children.Add(new TextBlock { Text = "megabytes of extra memory in devenv.exe" });
- var binding = new Binding()
- {
- Source = source,
- Path = new PropertyPath(sourcePropertyName)
- };
-
- base.AddBinding(tb.SetBinding(TextBox.TextProperty, binding));
+ panel.Children.Add(group);
- return tb;
+ // and add the rest of the options
+ base.AddOptions(panel);
}
}
}
diff --git a/src/VisualStudio/VisualStudioDiagnosticsToolWindow/VisualStudioDiagnosticsWindow.csproj b/src/VisualStudio/VisualStudioDiagnosticsToolWindow/VisualStudioDiagnosticsWindow.csproj
index 3ac32cdd595b2..4f860a12bc1ae 100644
--- a/src/VisualStudio/VisualStudioDiagnosticsToolWindow/VisualStudioDiagnosticsWindow.csproj
+++ b/src/VisualStudio/VisualStudioDiagnosticsToolWindow/VisualStudioDiagnosticsWindow.csproj
@@ -101,6 +101,7 @@
+
diff --git a/src/VisualStudio/VisualStudioDiagnosticsToolWindow/VisualStudioDiagnosticsWindowPackage.cs b/src/VisualStudio/VisualStudioDiagnosticsToolWindow/VisualStudioDiagnosticsWindowPackage.cs
index 8e538d946576a..cfd8bb89c7dd0 100644
--- a/src/VisualStudio/VisualStudioDiagnosticsToolWindow/VisualStudioDiagnosticsWindowPackage.cs
+++ b/src/VisualStudio/VisualStudioDiagnosticsToolWindow/VisualStudioDiagnosticsWindowPackage.cs
@@ -4,6 +4,9 @@
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Runtime.InteropServices;
+using Microsoft.CodeAnalysis.Options;
+using Microsoft.VisualStudio;
+using Microsoft.VisualStudio.ComponentModelHost;
using Microsoft.VisualStudio.LanguageServices.Implementation.Options;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
@@ -39,8 +42,11 @@ namespace Roslyn.VisualStudio.DiagnosticsWindow
[ProvideToolWindow(typeof(DiagnosticsWindow))]
[Guid(GuidList.guidVisualStudioDiagnosticsWindowPkgString)]
[Description("Roslyn Diagnostics Window")]
+ [ProvideAutoLoad(UIContextGuids80.SolutionExists, PackageAutoLoadFlags.BackgroundLoad)]
public sealed class VisualStudioDiagnosticsWindowPackage : Package
{
+ private ForceLowMemoryMode _forceLowMemoryMode;
+
///
/// This function is called when the user clicks the menu item that shows the
/// tool window. See the Initialize method to see how the menu item is associated to
@@ -72,6 +78,10 @@ protected override void Initialize()
{
base.Initialize();
+ var componentModel = (IComponentModel)GetService(typeof(SComponentModel));
+
+ _forceLowMemoryMode = new ForceLowMemoryMode(componentModel.GetService());
+
// Add our command handlers for menu (commands must exist in the .vsct file)
OleMenuCommandService mcs = GetService(typeof(IMenuCommandService)) as OleMenuCommandService;
if (null != mcs)
diff --git a/src/VisualStudio/VisualStudioDiagnosticsToolWindow/source.extension.vsixmanifest b/src/VisualStudio/VisualStudioDiagnosticsToolWindow/source.extension.vsixmanifest
index 81112ee54201e..e450b6e8fc219 100644
--- a/src/VisualStudio/VisualStudioDiagnosticsToolWindow/source.extension.vsixmanifest
+++ b/src/VisualStudio/VisualStudioDiagnosticsToolWindow/source.extension.vsixmanifest
@@ -16,6 +16,7 @@
+