提交 641ad84f 编写于 作者: A Andrew Casey

Manage the lifetime of DkmClrValue objects

We need to attach the same information to DkmEvaluationResults and
DkmEvaluationResultEnumContexts, but they have different lifetimes.  Enum
contexts, which are, in some sense, the children of evaluation results are
closed first.  As such we don't want to clean up our attached information
until the evaluation result is closed.  When we are informed that this has
happened (by a call to EvalResultDataItem.OnClose), we call Close on the
associated DkmClrValue.

We hope that actively managing the lifetime of DkmClrValue instances will
improve perf by reducing the amount of work that the debugger has to do on
each evaluation (which is proportional to the number of live
DkmClrValues).

Unfortunately, this will not improve perf in the large-array case because
DkmEvaluationResults are not closed as they are scrolled out of view.

Associated with DevDiv #1094428 (not yet on GitHub).
上级 91710c6a
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
// 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.Collections.Generic;
......
// 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 Microsoft.VisualStudio.Debugger;
namespace Microsoft.CodeAnalysis.ExpressionEvaluator
{
/// <summary>
/// This type exists to protect <see cref="ExpressionEvaluator.EvalResultDataItem"/> from
/// spurious <see cref="DkmDataItem.OnClose"/> calls. We need to attach the same information
/// to <see cref="Microsoft.VisualStudio.Debugger.Evaluation.DkmEvaluationResult"/> and
/// <see cref="Microsoft.VisualStudio.Debugger.Evaluation.DkmEvaluationResultEnumContext"/>
/// but they have different lifetimes. Enum contexts (which are effectively child lists)
/// are closed before the corresponding evaluation results. We don't want to actually clean
/// up until the evaluation result is closed.
/// </summary>
internal sealed class EnumContextDataItem : DkmDataItem
{
public readonly EvalResultDataItem EvalResultDataItem;
/// <remarks>
/// Only <see cref="ExpressionEvaluator.EvalResultDataItem"/> is expected to instantiate this type.
/// </remarks>
public EnumContextDataItem(EvalResultDataItem dataItem)
{
this.EvalResultDataItem = dataItem;
}
}
}
......@@ -110,5 +110,11 @@ private static DkmEvaluationResultFlags GetFlags(DkmClrValue value)
return resultFlags;
}
protected override void OnClose()
{
Debug.WriteLine("Closing " + FullName);
Value.Close();
}
}
}
......@@ -89,7 +89,7 @@ void IDkmClrResultProvider.GetItems(DkmEvaluationResultEnumContext enumContext,
{
try
{
var dataItem = enumContext.GetDataItem<EvalResultDataItem>();
var dataItem = enumContext.GetDataItem<EnumContextDataItem>();
if (dataItem == null)
{
// We don't know about this result. Call next implementation
......@@ -97,7 +97,7 @@ void IDkmClrResultProvider.GetItems(DkmEvaluationResultEnumContext enumContext,
return;
}
completionRoutine(GetItems(enumContext.InspectionContext, dataItem, startIndex, count));
completionRoutine(GetItems(enumContext.InspectionContext, dataItem.EvalResultDataItem, startIndex, count));
}
catch (Exception e) when (ExpressionEvaluatorFatalError.CrashIfFailFastEnabled(e))
{
......@@ -116,7 +116,7 @@ string IDkmClrResultProvider.GetUnderlyingString(DkmEvaluationResult result)
return result.GetUnderlyingString();
}
return dataItem.Value != null ? dataItem.Value.GetUnderlyingString() : null;
return dataItem.Value?.GetUnderlyingString();
}
catch (Exception e) when (ExpressionEvaluatorFatalError.CrashIfFailFastEnabled(e))
{
......@@ -420,7 +420,7 @@ private DkmGetChildrenAsyncResult GetChildren(DkmInspectionContext inspectionCon
var rows = builder.ToArrayAndFree();
Debug.Assert(index >= rows.Length);
Debug.Assert(initialRequestSize >= rows.Length);
var enumContext = DkmEvaluationResultEnumContext.Create(index, evaluationResult.StackFrame, evaluationResult.InspectionContext, dataItem);
var enumContext = DkmEvaluationResultEnumContext.Create(index, evaluationResult.StackFrame, evaluationResult.InspectionContext, new EnumContextDataItem(dataItem));
return new DkmGetChildrenAsyncResult(rows, enumContext);
}
......
......@@ -101,6 +101,7 @@
<Compile Include="Helpers\ArrayBuilder.cs" />
<Compile Include="Helpers\DkmClrValueFlagsExtensions.cs" />
<Compile Include="Helpers\DkmEvaluationResultFlagsExtensions.cs" />
<Compile Include="Helpers\EnumContextDataItem.cs" />
<Compile Include="Helpers\EvalResultDataItem.cs" />
<Compile Include="Helpers\GeneratedMetadataNames.cs" />
<Compile Include="Helpers\HashFunctions.cs" />
......@@ -136,3 +137,4 @@
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
</ImportGroup>
</Project>
......@@ -647,5 +647,9 @@ private unsafe static object Dereference(IntPtr ptr, Type elementType)
throw new InvalidOperationException();
}
}
public void Close()
{
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
#region Assembly Microsoft.VisualStudio.Debugger.Engine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
// References\Debugger\v2.0\Microsoft.VisualStudio.Debugger.Engine.dll
#endregion
namespace Microsoft.VisualStudio.Debugger
{
public class DkmDataItem
{
protected virtual void OnClose() { }
}
}
\ No newline at end of file
......@@ -7,7 +7,6 @@ namespace Microsoft.VisualStudio.Debugger
{
public delegate void DkmCompletionRoutine<TResult>(TResult result);
public class DkmDataItem { }
public class DkmWorkList { }
public enum DkmDataCreationDisposition
......
......@@ -120,6 +120,9 @@
<Compile Include="..\..\Source\ResultProvider\Helpers\EvalResultDataItem.cs">
<Link>ResultProvider\Helpers\EvalResultDataItem.cs</Link>
</Compile>
<Compile Include="..\..\Source\ResultProvider\Helpers\EnumContextDataItem.cs">
<Link>ResultProvider\Helpers\EnumContextDataItem.cs</Link>
</Compile>
<Compile Include="..\..\Source\ResultProvider\Helpers\GeneratedMetadataNames.cs">
<Link>ResultProvider\Helpers\GeneratedMetadataNames.cs</Link>
</Compile>
......@@ -174,6 +177,7 @@
<Compile Include="Debugger\Engine\DkmEvaluationResultFlags.cs" />
<Compile Include="Debugger\Engine\DkmFailedEvaluationResult.cs" />
<Compile Include="Debugger\Engine\DkmInspectionContext.cs" />
<Compile Include="Debugger\Engine\DkmDataItem.cs" />
<Compile Include="Debugger\Engine\DkmMisc.cs" />
<Compile Include="Debugger\Engine\DkmModule.cs" />
<Compile Include="Debugger\Engine\DkmModuleInstance.cs" />
......@@ -221,3 +225,4 @@
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
</ImportGroup>
</Project>
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册