Browse Source

CallStackPad refresh does Application.DoEvents() as well.

DoEvents() called very often.  
New class for logging time measurements to the console.  
If one OnPause delegate resumes process, remaining delegates are not called.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@2906 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
David Srbecký 19 years ago
parent
commit
9bd0aec201
  1. 2
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Debugger.AddIn.csproj
  2. 64
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Pads/CallStackPad.cs
  3. 19
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Pads/LocalVarPad.cs
  4. 19
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Service/WindowsDebugger.cs
  5. 8
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/Adapters/DynamicTreeDebuggerRow.cs
  6. 8
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/Adapters/TreeViewNode.cs
  7. 4
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/ArrayRangeNode.cs
  8. 12
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/ChildNodesOfObject.cs
  9. 2
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/StackFrameNode.cs
  10. 77
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/Util.cs
  11. 88
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/Utils.cs
  12. 4
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/ValueNode.cs
  13. 10
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Process-StateControl.cs

2
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Debugger.AddIn.csproj

@ -77,7 +77,7 @@ @@ -77,7 +77,7 @@
<Compile Include="Src\TreeModel\ISetText.cs" />
<Compile Include="Src\TreeModel\ChildNodesOfObject.cs" />
<Compile Include="Src\TreeModel\StackFrameNode.cs" />
<Compile Include="Src\TreeModel\Util.cs" />
<Compile Include="Src\TreeModel\Utils.cs" />
<None Include="COPYING" />
</ItemGroup>
<ItemGroup>

64
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Pads/CallStackPad.cs

@ -44,6 +44,7 @@ using System.Text; @@ -44,6 +44,7 @@ using System.Text;
using System.Windows.Forms;
using Debugger;
using Debugger.AddIn.TreeModel;
using ICSharpCode.Core;
namespace ICSharpCode.SharpDevelop.Gui.Pads
@ -124,32 +125,52 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -124,32 +125,52 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
public override void RefreshPad()
{
DateTime start = Debugger.Util.HighPrecisionTimer.Now;
if (debuggedProcess == null || debuggedProcess.IsRunning || debuggedProcess.SelectedThread == null) {
callStackList.Items.Clear();
return;
}
using(new PrintTimes("Callstack refresh")) {
try {
Utils.DoEvents(debuggedProcess.DebuggeeState);
List<ListViewItem> items = CreateItems();
UpdateItems(items);
} catch(AbortedBecauseDebuggeeResumedException) {
}
}
}
public List<ListViewItem> CreateItems()
{
bool showExternalMethods = ShowExternalMethods;
bool lastItemIsExternalMethod = false;
List<ListViewItem> items = new List<ListViewItem>();
if (debuggedProcess != null && debuggedProcess.SelectedThread != null && debuggedProcess.IsPaused) {
foreach (StackFrame frame in debuggedProcess.SelectedThread.GetCallstack(100)) {
ListViewItem item;
if (frame.HasSymbols || showExternalMethods) {
// Show the method in the list
item = new ListViewItem(new string[] { GetFullName(frame), "" });
lastItemIsExternalMethod = false;
} else {
// Show [External methods] in the list
if (lastItemIsExternalMethod) continue;
item = new ListViewItem(new string[] { ResourceService.GetString("MainWindow.Windows.Debug.CallStack.ExternalMethods"), "" });
lastItemIsExternalMethod = true;
}
item.Tag = frame;
item.ForeColor = frame.HasSymbols ? Color.Black : Color.Gray;
items.Add(item);
foreach (StackFrame frame in debuggedProcess.SelectedThread.GetCallstack(100)) {
ListViewItem item;
if (frame.HasSymbols || showExternalMethods) {
// Show the method in the list
item = new ListViewItem(new string[] { GetFullName(frame), "" });
lastItemIsExternalMethod = false;
} else {
// Show [External methods] in the list
if (lastItemIsExternalMethod) continue;
item = new ListViewItem(new string[] { ResourceService.GetString("MainWindow.Windows.Debug.CallStack.ExternalMethods"), "" });
lastItemIsExternalMethod = true;
}
item.Tag = frame;
item.ForeColor = frame.HasSymbols ? Color.Black : Color.Gray;
items.Add(item);
Utils.DoEvents(debuggedProcess.DebuggeeState);
}
return items;
}
public void UpdateItems(List<ListViewItem> items)
{
callStackList.BeginUpdate();
// Adjust count
while (callStackList.Items.Count < items.Count) {
@ -164,11 +185,10 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -164,11 +185,10 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
callStackList.Items[i].SubItems[1] = items[i].SubItems[1];
callStackList.Items[i].Tag = items[i].Tag;
callStackList.Items[i].ForeColor = items[i].ForeColor;
Utils.DoEvents(debuggedProcess.DebuggeeState);
}
callStackList.EndUpdate();
DateTime end = Debugger.Util.HighPrecisionTimer.Now;
LoggingService.InfoFormatted("Callstack pad refreshed ({0} ms)", (end - start).TotalMilliseconds);
}
public string GetFullName(StackFrame frame)

19
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Pads/LocalVarPad.cs

@ -223,19 +223,18 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -223,19 +223,18 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
public override void RefreshPad()
{
Debugger.AddIn.TreeModel.Util.ForceDoEvents();
DateTime start = Debugger.Util.HighPrecisionTimer.Now;
try {
if (debuggedProcess != null && debuggedProcess.SelectedStackFrame != null) {
if (debuggedProcess == null || debuggedProcess.IsRunning || debuggedProcess.SelectedStackFrame == null) {
localVarList.Root.Children.Clear();
return;
}
using(new PrintTimes("Local Variables refresh")) {
try {
Utils.DoEvents(debuggedProcess.DebuggeeState);
TreeViewNode.SetContentRecursive(this, localVarList.Root.Children, new StackFrameNode(debuggedProcess.SelectedStackFrame).ChildNodes);
} else {
//TreeViewNode.SetContentRecursive(this, localVarList.Root.Children, null);
} catch(AbortedBecauseDebuggeeResumedException) {
}
} catch(AbortedBecauseDebugeeStateExpiredException) {
LoggingService.Info("Aborted variable refresh because debugee state expired");
}
DateTime end = Debugger.Util.HighPrecisionTimer.Now;
LoggingService.InfoFormatted("Local Variables pad refreshed ({0} ms)", (end - start).TotalMilliseconds);
}
}
}

19
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Service/WindowsDebugger.cs

@ -297,7 +297,7 @@ namespace ICSharpCode.SharpDevelop.Services @@ -297,7 +297,7 @@ namespace ICSharpCode.SharpDevelop.Services
currentTooltipExpression = val.Expression;
currentTooltipRow = new DynamicTreeDebuggerRow(DebuggedProcess, new ValueNode(val));
return new DebuggerGridControl(currentTooltipRow);
} catch (AbortedBecauseDebugeeStateExpiredException) {
} catch (AbortedBecauseDebuggeeResumedException) {
return null;
}
}
@ -437,18 +437,25 @@ namespace ICSharpCode.SharpDevelop.Services @@ -437,18 +437,25 @@ namespace ICSharpCode.SharpDevelop.Services
void debuggedProcess_DebuggingPaused(object sender, ProcessEventArgs e)
{
OnIsProcessRunningChanged(EventArgs.Empty);
JumpToCurrentLine();
using(new PrintTimes("Jump to current line")) {
JumpToCurrentLine();
}
if (currentTooltipRow != null && currentTooltipRow.IsShown) {
AbstractNode updatedNode = Debugger.AddIn.TreeModel.Util.CreateNode(currentTooltipExpression);
try {
currentTooltipRow.SetContentRecursive(updatedNode);
} catch (AbortedBecauseDebugeeStateExpiredException) {
using(new PrintTimes("Update tooltip")) {
try {
Utils.DoEvents(debuggedProcess.DebuggeeState);
AbstractNode updatedNode = Debugger.AddIn.TreeModel.Utils.CreateNode(currentTooltipExpression);
currentTooltipRow.SetContentRecursive(updatedNode);
} catch (AbortedBecauseDebuggeeResumedException) {
}
}
}
}
void debuggedProcess_DebuggingResumed(object sender, ProcessEventArgs e)
{
OnIsProcessRunningChanged(EventArgs.Empty);
DebuggerService.RemoveCurrentLineMarker();
}

8
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/Adapters/DynamicTreeDebuggerRow.cs

@ -83,11 +83,7 @@ namespace Debugger.AddIn.TreeModel @@ -83,11 +83,7 @@ namespace Debugger.AddIn.TreeModel
}
// Repaint and process user commands
DebuggeeState state = process.DebuggeeState;
Util.DoEvents();
if (process.IsRunning || state.HasExpired) {
throw new AbortedBecauseDebugeeStateExpiredException();
}
Utils.DoEvents(process.DebuggeeState);
}
public void SetChildContentRecursive(IEnumerable<AbstractNode> contentEnum)
@ -122,7 +118,7 @@ namespace Debugger.AddIn.TreeModel @@ -122,7 +118,7 @@ namespace Debugger.AddIn.TreeModel
base.OnExpanding(e);
try {
LoadChilds();
} catch (AbortedBecauseDebugeeStateExpiredException) {
} catch (AbortedBecauseDebuggeeResumedException) {
}
}

8
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/Adapters/TreeViewNode.cs

@ -70,11 +70,7 @@ namespace Debugger.AddIn.TreeModel @@ -70,11 +70,7 @@ namespace Debugger.AddIn.TreeModel
}
this.Tree.Invalidate();
// Repaint and process user commands
DebuggeeState state = localVarPad.Process.DebuggeeState;
Util.DoEvents();
if (localVarPad.Process.IsRunning || state.HasExpired) {
throw new AbortedBecauseDebugeeStateExpiredException();
}
Utils.DoEvents(localVarPad.Process.DebuggeeState);
}
public static void SetContentRecursive(LocalVarPad localVarPad, IList<TreeNodeAdv> childNodes, IEnumerable<AbstractNode> contentEnum)
@ -120,7 +116,7 @@ namespace Debugger.AddIn.TreeModel @@ -120,7 +116,7 @@ namespace Debugger.AddIn.TreeModel
expandedNodes[FullName] = true;
try {
LoadChilds();
} catch (AbortedBecauseDebugeeStateExpiredException) {
} catch (AbortedBecauseDebuggeeResumedException) {
}
}

4
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/ArrayRangeNode.cs

@ -15,12 +15,12 @@ using Debugger.Expressions; @@ -15,12 +15,12 @@ using Debugger.Expressions;
namespace Debugger.AddIn.TreeModel
{
public partial class Util
public partial class Utils
{
public static IEnumerable<AbstractNode> GetChildNodesOfArray(Expression expression, ArrayDimensions dimensions)
{
foreach(Expression childExpr in expression.AppendIndexers(dimensions)) {
yield return Util.CreateNode(childExpr);
yield return Utils.CreateNode(childExpr);
}
}
}

12
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/ChildNodesOfObject.cs

@ -16,7 +16,7 @@ using Debugger.Expressions; @@ -16,7 +16,7 @@ using Debugger.Expressions;
namespace Debugger.AddIn.TreeModel
{
public partial class Util
public partial class Utils
{
public static IEnumerable<AbstractNode> GetChildNodesOfObject(Expression targetObject, DebugType shownType)
{
@ -33,7 +33,7 @@ namespace Debugger.AddIn.TreeModel @@ -33,7 +33,7 @@ namespace Debugger.AddIn.TreeModel
yield return new StaticMembersNode(targetObject, shownType);
}
foreach(Expression childExpr in targetObject.AppendObjectMembers(shownType, Flags)) {
yield return Util.CreateNode(childExpr);
yield return Utils.CreateNode(childExpr);
}
}
}
@ -51,7 +51,7 @@ namespace Debugger.AddIn.TreeModel @@ -51,7 +51,7 @@ namespace Debugger.AddIn.TreeModel
this.Image = DebuggerIcons.ImageList.Images[0]; // Class
this.Name = StringParser.Parse("${res:MainWindow.Windows.Debug.LocalVariables.BaseClass}");
this.Type = shownType.FullName;
this.ChildNodes = Util.GetChildNodesOfObject(targetObject, shownType);
this.ChildNodes = Utils.GetChildNodesOfObject(targetObject, shownType);
}
}
@ -74,7 +74,7 @@ namespace Debugger.AddIn.TreeModel @@ -74,7 +74,7 @@ namespace Debugger.AddIn.TreeModel
IEnumerable<AbstractNode> GetChildNodes()
{
foreach(Expression childExpr in targetObject.AppendObjectMembers(shownType, Flags)) {
yield return Util.CreateNode(childExpr);
yield return Utils.CreateNode(childExpr);
}
}
}
@ -101,7 +101,7 @@ namespace Debugger.AddIn.TreeModel @@ -101,7 +101,7 @@ namespace Debugger.AddIn.TreeModel
yield return new NonPublicStaticMembersNode(targetObject, shownType);
}
foreach(Expression childExpr in targetObject.AppendObjectMembers(shownType, Flags)) {
yield return Util.CreateNode(childExpr);
yield return Utils.CreateNode(childExpr);
}
}
}
@ -125,7 +125,7 @@ namespace Debugger.AddIn.TreeModel @@ -125,7 +125,7 @@ namespace Debugger.AddIn.TreeModel
IEnumerable<AbstractNode> GetChildNodes()
{
foreach(Expression childExpr in targetObject.AppendObjectMembers(shownType, Flags)) {
yield return Util.CreateNode(childExpr);
yield return Utils.CreateNode(childExpr);
}
}
}

2
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/StackFrameNode.cs

@ -32,7 +32,7 @@ namespace Debugger.AddIn.TreeModel @@ -32,7 +32,7 @@ namespace Debugger.AddIn.TreeModel
IEnumerable<AbstractNode> GetChildNodes()
{
foreach(Expression expr in Expression.MethodVariables(stackFrame.MethodInfo)) {
yield return Util.CreateNode(expr);
yield return Utils.CreateNode(expr);
}
}
}

77
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/Util.cs

@ -1,77 +0,0 @@ @@ -1,77 +0,0 @@
// <file>
// <copyright license="BSD-new" see="prj:///COPYING"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Windows.Forms;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Debugging;
using ICSharpCode.SharpDevelop.Services;
using Debugger.Expressions;
namespace Debugger.AddIn.TreeModel
{
public static partial class Util
{
static DateTime nextDoEventsTime = Debugger.Util.HighPrecisionTimer.Now;
const double workLoad = 0.75; // Fraction of getting variables vs. repainting
const double maxFPS = 30; // this prevents too much drawing on good machine
const double maxWorkTime = 150; // ms this ensures minimal response on bad machine
public static void ResetDoEventsStartTime()
{
nextDoEventsTime = Debugger.Util.HighPrecisionTimer.Now.AddMilliseconds(1000 / maxFPS);
}
public static void ForceDoEvents()
{
nextDoEventsTime = DateTime.MinValue;
DoEvents();
}
public static void DoEvents()
{
if (Debugger.Util.HighPrecisionTimer.Now > nextDoEventsTime) {
DateTime start = Debugger.Util.HighPrecisionTimer.Now;
LoggingService.InfoFormatted("Application.DoEvents()");
Application.DoEvents();
DateTime end = Debugger.Util.HighPrecisionTimer.Now;
double doEventsDuration = (end - start).TotalMilliseconds;
double minWorkTime = 1000 / maxFPS - doEventsDuration; // ms
double workTime = (doEventsDuration / (1 - workLoad)) * workLoad;
workTime = Math.Max(minWorkTime, Math.Min(maxWorkTime, workTime)); // Clamp
nextDoEventsTime = end.AddMilliseconds(workTime);
double fps = 1000 / (doEventsDuration + workTime);
// LoggingService.InfoFormatted("Rendering: {0} ms => work budget: {1} ms ({2:f1} FPS)", doEventsDuration, workTime, fps);
}
}
public static AbstractNode CreateNode(Expression expression)
{
try {
Value val = expression.Evaluate(WindowsDebugger.DebuggedProcess.SelectedStackFrame);
return new ValueNode(val);
} catch (GetValueException e) {
return new ErrorNode(expression, e);
}
}
public static WindowsDebugger WindowsDebugger {
get {
return (WindowsDebugger)DebuggerService.CurrentDebugger;
}
}
}
public class AbortedBecauseDebugeeStateExpiredException: System.Exception
{
public AbortedBecauseDebugeeStateExpiredException(): base()
{
}
}
}

88
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/Utils.cs

@ -0,0 +1,88 @@ @@ -0,0 +1,88 @@
// <file>
// <copyright license="BSD-new" see="prj:///COPYING"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Windows.Forms;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Debugging;
using ICSharpCode.SharpDevelop.Services;
using Debugger.Expressions;
namespace Debugger.AddIn.TreeModel
{
public static partial class Utils
{
public static void DoEvents(DebuggeeState debuggeeState)
{
if (debuggeeState == null) {
throw new ArgumentNullException();
}
if (debuggeeState.HasExpired) {
throw new System.Exception("State is expired before DoEvents");
}
//using(new PrintTimes("Application.DoEvents()"))
{
Application.DoEvents();
}
if (debuggeeState.HasExpired) {
LoggingService.Info("Aborted because debuggee resumed");
throw new AbortedBecauseDebuggeeResumedException();
}
}
public static AbstractNode CreateNode(Expression expression)
{
try {
Value val = expression.Evaluate(WindowsDebugger.DebuggedProcess.SelectedStackFrame);
return new ValueNode(val);
} catch (GetValueException e) {
return new ErrorNode(expression, e);
}
}
public static WindowsDebugger WindowsDebugger {
get {
return (WindowsDebugger)DebuggerService.CurrentDebugger;
}
}
}
public class AbortedBecauseDebuggeeResumedException: System.Exception
{
public AbortedBecauseDebuggeeResumedException(): base()
{
}
}
public class PrintTimes: PrintTime
{
public PrintTimes(string text): base(text + " - end")
{
LoggingService.InfoFormatted("{0} - start", text);
}
}
public class PrintTime: IDisposable
{
string text;
DateTime start;
public PrintTime(string text)
{
this.text = text;
this.start = Debugger.Util.HighPrecisionTimer.Now;
}
public void Dispose()
{
TimeSpan dur = Debugger.Util.HighPrecisionTimer.Now - start;
LoggingService.InfoFormatted("{0} ({1} ms)", text, dur.TotalMilliseconds);
}
}
}

4
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/ValueNode.cs

@ -63,9 +63,9 @@ namespace Debugger.AddIn.TreeModel @@ -63,9 +63,9 @@ namespace Debugger.AddIn.TreeModel
// Note that these return enumerators so they are lazy-evaluated
if (val.IsObject) {
this.ChildNodes = Util.GetChildNodesOfObject(this.Expression, val.Type);
this.ChildNodes = Utils.GetChildNodesOfObject(this.Expression, val.Type);
} else if (val.IsArray) {
this.ChildNodes = Util.GetChildNodesOfArray(this.Expression, val.ArrayDimensions);
this.ChildNodes = Utils.GetChildNodesOfArray(this.Expression, val.ArrayDimensions);
} else {
this.ChildNodes = null;
}

10
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Process-StateControl.cs

@ -25,14 +25,22 @@ namespace Debugger @@ -25,14 +25,22 @@ namespace Debugger
// HACK: public
public virtual void OnPaused()
{
AssertPaused();
TraceMessage ("Debugger event: OnPaused()");
if (Paused != null) {
Paused(this, new ProcessEventArgs(this));
foreach(Delegate d in Paused.GetInvocationList()) {
if (IsRunning) {
TraceMessage ("Skipping OnPaused delegate becuase process has resumed");
break;
}
d.DynamicInvoke(this, new ProcessEventArgs(this));
}
}
}
protected virtual void OnResumed()
{
AssertRunning();
TraceMessage ("Debugger event: OnResumed()");
if (Resumed != null) {
Resumed(this, new ProcessEventArgs(this));

Loading…
Cancel
Save