diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/ValueProviders/GridValuesProvider.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/ValueProviders/GridValuesProvider.cs index f8be3e2ca1..f656934db6 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/ValueProviders/GridValuesProvider.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/ValueProviders/GridValuesProvider.cs @@ -35,7 +35,8 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer /// public IList GetItemTypeMembers() { - return itemType.GetFieldsAndNonIndexedProperties(BindingFlags.Public | BindingFlags.Instance); + var publicPropetiesAndFields = itemType.GetFieldsAndNonIndexedProperties(BindingFlags.Public | BindingFlags.Instance); + return publicPropetiesAndFields; } } } diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/ValueProviders/ListValuesProvider.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/ValueProviders/ListValuesProvider.cs index 9859524667..22aed132d9 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/ValueProviders/ListValuesProvider.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/ValueProviders/ListValuesProvider.cs @@ -5,6 +5,7 @@ using System; using Debugger.AddIn.Visualizers.Common; using Debugger.AddIn.Visualizers.Utils; using Debugger.MetaData; +using ICSharpCode.Core; using ICSharpCode.NRefactory.Ast; using ICSharpCode.SharpDevelop.Services; using System.Reflection; @@ -16,8 +17,12 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer /// public class ListValuesProvider : GridValuesProvider, IListValuesProvider { - private bool countEvaluated = false; - private int count = -1; + int? listCount = null; + /// + /// After evaluating how many items to clear debugger Expression cache, + /// so that the cache does not keep too many PermanentReferences. + /// + static readonly int ClearCacheThreshold = 50; public ListValuesProvider(Expression targetObject, DebugType listItemType) :base(targetObject, listItemType) @@ -26,16 +31,23 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer public int GetCount() { - if (!countEvaluated) - { - this.count = Debugger.AddIn.TreeModel.Utils.GetIListCount(this.targetObject); - countEvaluated = true; + if (this.listCount == null) { + this.listCount = Debugger.AddIn.TreeModel.Utils.GetIListCount(this.targetObject); } - return this.count; + return this.listCount.Value; } + /// When this reaches ClearCacheThreshold, the debugger Expression cache is cleared. + int itemClearCacheCounter = 0; + public ObjectValue GetItemAt(int index) { + if (itemClearCacheCounter++ > ClearCacheThreshold) { + // clear debugger Expression cache to avoid holding too many PermanentReferences + WindowsDebugger.CurrentProcess.ClearExpressionCache(); + LoggingService.Info("Cleared debugger Expression cache."); + itemClearCacheCounter = 0; + } return ObjectValue.Create( targetObject.AppendIndexer(index).Evaluate(WindowsDebugger.CurrentProcess), //targetObject.AppendIndexer(index), // use Expression instead of value - possible only for IList though diff --git a/src/AddIns/Debugger/Debugger.Core/Process.cs b/src/AddIns/Debugger/Debugger.Core/Process.cs index eec5f36165..cc405eb9ca 100644 --- a/src/AddIns/Debugger/Debugger.Core/Process.cs +++ b/src/AddIns/Debugger/Debugger.Core/Process.cs @@ -531,6 +531,19 @@ namespace Debugger // This is done once ExitProcess callback is received } + /// + /// Clears the internal Expression cache used too speed up Expression evaluation. + /// Use this if your code evaluates expressions in a way which would cause + /// the cache to grow too large. The cache holds PermanentReferences so it + /// shouldn't grow larger than a few hundred items. + /// + public void ClearExpressionCache() + { + if (this.ExpressionsCache != null ){ + this.ExpressionsCache.Clear(); + } + } + void SelectSomeThread() { if (this.SelectedThread != null && !this.SelectedThread.IsInValidState) {