Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Breakpoint Label frame to optimize debug stepping performance #2190

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

JustinGrote
Copy link
Collaborator

@JustinGrote JustinGrote commented Oct 12, 2024

PR Summary

Implements DAP DelayedStackTraceLoading and returns an artificial breakpoint label frame based on the invocation info ASAP once the debugger stops. The rest of the stack trace is then returned on a future request that doesn't block the client UI.

Capture.mp4

PR Context

Debug stepping takes 300ms+ due to waiting for stack trace collection via the slow Get-PSCallStack "hack". Further improvements will come around this later.

@JustinGrote JustinGrote self-assigned this Oct 12, 2024
@JustinGrote JustinGrote changed the title Add Breakpoint label frame to optimize debug stepping performance Add Breakpoint Label frame to optimize debug stepping performance Oct 12, 2024
@JustinGrote
Copy link
Collaborator Author

JustinGrote commented Oct 12, 2024

@SeeminglyScience @andyleejordan I made this a fairly minimal PR to be easy to review. Additional things I plan to do next as future incrementals

  • Add start/end/column positioning to all stack frames (it's available in the position property, just has to be serialized properly)
  • Separate variable and frame processing into independent resolution paths
  • Implement "fast path" for local runspace sessions to use the runspace debugger properties and methods rather than going thru the pipeline to fetch the frame info, ~2-3ms vs 300ms-800ms
  • Move all the scope/stack/variable resolution to a new async-based DebugStoppedContext class that can be disposed and re-instantiated cleanly and kept separate from the DebugService concerns, since LSP spec says no IDs/etc. should be reused between debug adapter stop/resumes

@andyleejordan
Copy link
Member

@SeeminglyScience @andyleejordan I made this a fairly minimal PR to be easy to review. Additional things I plan to do next as future incrementals

  • Add start/end/column positioning to all stack frames (it's available in the position property, just has to be serialized properly)
  • Separate variable and frame processing into independent resolution paths
  • Implement "fast path" for local runspace sessions to use the runspace debugger properties and methods rather than going thru the pipeline to fetch the frame info, ~2-3ms vs 300ms-800ms
  • Move all the scope/stack/variable resolution to a new async-based DebugStoppedContext class that can be disposed and re-instantiated cleanly and kept separate from the DebugService concerns, since LSP spec says no IDs/etc. should be reused between debug adapter stop/resumes

I'm super excited for all of this.

Copy link
Member

@andyleejordan andyleejordan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@SeeminglyScience and I are going to take a closer look at this just to be sure nothing got missed.

@JustinGrote
Copy link
Collaborator Author

This has been rebased to the latest prerelease and is good for re-review.

Copy link
Collaborator

@SeeminglyScience SeeminglyScience left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Justin! Couple of questions and minor requests

Copy link
Member

@andyleejordan andyleejordan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Loving this, we finally got to review through it. Just a couple changes requested and then we want to get into pre-release.

VariableScope[] variableScopes =
_debugService.GetVariableScopes(
(int)request.FrameId);
//We have an artificial breakpoint label, so just copy the stacktrace from the first stack entry for this.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
//We have an artificial breakpoint label, so just copy the stacktrace from the first stack entry for this.
// We have an artificial breakpoint label, so just copy the stacktrace from the first stack entry for this.

Could ou explain why this is either 0, or (and this is what's changed) FrameId - 1? That means there are two instances where we get scope 0: FrameId == 0 and FrameId == 1.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Uh, there was a reason, but I honestly don't remember at this point. Let me check

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot reviewed 5 out of 5 changed files in this pull request and generated no suggestions.

@JustinGrote
Copy link
Collaborator Author

@andyleejordan @SeeminglyScience your opinions have officially been deemed irrelevant by our AI overlords, please approve as is /s
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants