Change:
} })); <del> const statusQueue = new Queue<void>(); this.rawListeners.add(this.raw.onDidStop(async event => { statusQueue.queue(async () => { this.passFocusScheduler.cancel(); this.stoppedDetails.push(event.body); await this.fetchThreads(event.body); // If the focus for the current session is on a non-existent thread, clear the focus. const focusedThread = this.debugService.getViewModel().focusedThread; const focusedThreadDoesNotExist = focusedThread !== undefined && focusedThread.session === this && !this.threads.has(focusedThread.threadId); if (focusedThreadDoesNotExist) { this.debugService.focusStackFrame(undefined, undefined); } const thread = typeof event.body.threadId === 'number' ? this.getThread(event.body.threadId) : undefined; if (thread) { // Call fetch call stack twice, the first only return the top stack frame. // Second retrieves the rest of the call stack. For performance reasons #25605 const promises = this.model.refreshTopOfCallstack(<Thread>thread); const focus = async () => { if (focusedThreadDoesNotExist || (!event.body.preserveFocusHint && thread.getCallStack().length)) { const focusedStackFrame = this.debugService.getViewModel().focusedStackFrame; if (!focusedStackFrame || focusedStackFrame.thread.session === this) { // Only take focus if nothing is focused, or if the focus is already on the current session const preserveFocus = !this.configurationService.getValue<IDebugConfiguration>('debug').focusEditorOnBreak; await this.debugService.focusStackFrame(undefined, thread, undefined, { preserveFocus }); } if (thread.stoppedDetails) { if (thread.stoppedDetails.reason === 'breakpoint' && this.configurationService.getValue<IDebugConfiguration>('debug').openDebug === 'openOnDebugBreak' && !this.suppressDebugView) { await this.paneCompositeService.openPaneComposite(VIEWLET_ID, ViewContainerLocation.Sidebar); </del> <ins> const statusQueue = this.rawListeners.add(new ThreadStatusScheduler()); this.rawListeners.add(this.raw.onDidStop(async event => { this.passFocusScheduler.cancel(); this.stoppedDetails.push(event.body); statusQueue.run( this.fetchThreads(event.body).then(() => event.body.threadId === undefined ? this.threadIds : [event.body.threadId]), async (threadId, token) => { const hasLotsOfThreads = event.body.threadId === undefined && this.threadIds.length > 10; // If the focus for the current session is on a non-existent thread, clear the focus. const focusedThread = this.debugService.getViewModel().focusedThread; const focusedThreadDoesNotExist = focusedThread !== undefined && focusedThread.session === this && !this.threads.has(focusedThread.threadId); if (focusedThreadDoesNotExist) { this.debugService.focusStackFrame(undefined, undefined); } const thread = typeof threadId === 'number' ? this.getThread(threadId) : undefined; if (thread) { // Call fetch call stack twice, the first only return the top stack frame. // Second retrieves the rest of the call stack. For performance reasons #25605 // Second call is only done if there's few threads that stopped in this event. const promises = this.model.refreshTopOfCallstack(<Thread>thread, /* fetchFullStack= */!hasLotsOfThreads); const focus = async () => { if (focusedThreadDoesNotExist || (!event.body.preserveFocusHint && thread.getCallStack().length)) { const focusedStackFrame = this.debugService.getViewModel().focusedStackFrame; if (!focusedStackFrame || focusedStackFrame.thread.session === this) { // Only take focus if nothing is focused, or if the focus is already on the current session const preserveFocus = !this.configurationService.getValue<IDebugConfiguration>('debug').focusEditorOnBreak; await this.debugService.focusStackFrame(undefined, thread, undefined, { preserveFocus }); </ins> } <del> if (this.configurationService.getValue<IDebugConfiguration>('debug').focusWindowOnBreak && !this.workbenchEnvironmentService.extensionTestsLocationURI) { await this.hostService.focus(window, { force: true /* Application may not be active */ }); </del> <ins> if (thread.stoppedDetails && !token.isCancellationRequested) { if (thread.stoppedDetails.reason === 'breakpoint' && this.configurationService.getValue<IDebugConfiguration>('debug').openDebug === 'openOnDebugBreak' && !this.suppressDebugView) { await this.paneCompositeService.openPaneComposite(VIEWLET_ID, ViewContainerLocation.Sidebar); } if (this.configurationService.getValue<IDebugConfiguration>('debug').focusWindowOnBreak && !this.workbenchEnvironmentService.extensionTestsLocationURI) { await this.hostService.focus(window, { force: true /* Application may not be active */ }); } </ins> } } <ins> }; await promises.topCallStack; if (token.isCancellationRequested) { return; </ins> } <del> }; await promises.topCallStack; focus(); await promises.wholeCallStack; const focusedStackFrame = this.debugService.getViewModel().focusedStackFrame; if (!focusedStackFrame || !focusedStackFrame.source || focusedStackFrame.source.presentationHint === 'deemphasize' || focusedStackFrame.presentationHint === 'deemphasize') { // The top stack frame can be deemphesized so try to focus again #68616 </del> focus(); <ins> await promises.wholeCallStack; if (token.isCancellationRequested) { return; } const focusedStackFrame = this.debugService.getViewModel().focusedStackFrame; if (!focusedStackFrame || !focusedStackFrame.source || focusedStackFrame.source.presentationHint === 'deemphasize' || focusedStackFrame.presentationHint === 'deemphasize') { // The top stack frame can be deemphesized so try to focus again #68616 focus(); } </ins> } <del> } this._onDidChangeState.fire(); }); </del> <ins> this._onDidChangeState.fire(); }, ); </ins> })); this.rawListeners.add(this.raw.onDidThread(event => { <del> statusQueue.queue(async () => { if (event.body.reason === 'started') { // debounce to reduce threadsRequest frequency and improve performance if (!this.fetchThreadsScheduler) { this.fetchThreadsScheduler = new RunOnceScheduler(() => { this.fetchThreads(); }, 100); this.rawListeners.add(this.fetchThreadsScheduler); } if (!this.fetchThreadsScheduler.isScheduled()) { this.fetchThreadsScheduler.schedule(); } } else if (event.body.reason === 'exited') { this.model.clearThreads(this.getId(), true, event.body.threadId); const viewModel = this.debugService.getViewModel(); const focusedThread = viewModel.focusedThread; this.passFocusScheduler.cancel(); if (focusedThread && event.body.threadId === focusedThread.threadId) { // De-focus the thread in case it was focused this.debugService.focusStackFrame(undefined, undefined, viewModel.focusedSession, { explicit: false }); } </del> <ins> statusQueue.cancel([event.body.threadId]); if (event.body.reason === 'started') { // debounce to reduce threadsRequest frequency and improve performance if (!this.fetchThreadsScheduler) { this.fetchThreadsScheduler = new RunOnceScheduler(() => { this.fetchThreads(); }, 100); this.rawListeners.add(this.fetchThreadsScheduler); </ins> } <del> }); </del> <ins> if (!this.fetchThreadsScheduler.isScheduled()) { this.fetchThreadsScheduler.schedule(); } } else if (event.body.reason === 'exited') { this.model.clearThreads(this.getId(), true, event.body.threadId); const viewModel = this.debugService.getViewModel(); const focusedThread = viewModel.focusedThread; this.passFocusScheduler.cancel(); if (focusedThread && event.body.threadId === focusedThread.threadId) { // De-focus the thread in case it was focused this.debugService.focusStackFrame(undefined, undefined, viewModel.focusedSession, { explicit: false }); } } </ins> })); this.rawListeners.add(this.raw.onDidTerminateDebugee(async event => {

Discussion:
Type: <bPerformance Issue</bWhen I step into my code (NodeJS), I noticed lately that the debugger is slower upon stepping in or over. I don't recall having this issue before though. It's a slight lag. I tried clearing my cache but that seemed to have no effect. VS Code version: Code 1.79.2 (, 2023-06-14T08:57:04.379Z) OS version: WindowsNT x64 10.0. Modes: <details<summarySystem Info</summary </details<details<summaryWorkspace Info</summary</details<details<summaryExtensions (9)</summaryExtensionVersion ------ vscode-css-formatter1.0.2 classdiagram-ts0.1.67 jsonviewer1.3.2 javascript-ejs-support1.3.3 gitlens14.0.1 vscode-firefox-debug2.9.8 debug-visualizer2.4.0 hexeditor1.9.11 php-debug1.32.1 </details<!-- generated by issue reporter --
Just following up. I actually reformatted my computer and upgraded to Windows 11 if that helps. And I am still getting lag with the step cursor (specifically with the Node debugger). When using the step cursor and XDebug, it's normal responsive speed.
/jsDebugLogs
Please collect trace logs using the following instructions:
It doesn't look like you ran a "step into" when you recorded those logs. Please do so so I can see what's going on.
Sorry about that. More data should be available in this log file.
There's a lot going on there. I think your case might have already been fixed by You can try out the of the debugger and see.
Oh sorry I did too much lol. Ok, I can live with this until the next fix. I'll keep an eye out for this on the next update. If I notice the debugger is still slow after next official update, I will just open this ticket again.
Also my title is a little inaccurate. It's not slow on just "step into". But also "step over" as well.
Sorta like VSCode decided to throttle the keystrokes. When the instruction is executed, its normal speed. But when I keep pressing F10 its not as responsive as it used to be.

For example, when I press F10 10 times, I expect responsiveness. But lately there seems to be latency between keystrokes.
There will always be some latency because events are queued and ultimately multiple round trips through the debugger and back to are required. But from the logs it looks like your rapid strokes might be getting you into the "bad state" I referenced in the PR where spooky things start happening. I'll close this for now, please comment if you hit this on nightly/in the next release (scheduled for 6 to 7 days from now)
I haven't tried the nightly release because I figured I would wait. But it's been awhile now, and I am still experiencing this problem. Debugging is still slow on version 1.81.0
Please grab another log file if you're able. Thanks!
Sure, I just debugged a very simple hello world app, barebones. Looping through an array from 1 through 10.
Can you grab a record of your screen during this? is useful. Also, please run so we can see when you trigger actions using keybindings, if any.
Yes, no problem. Please see the issue via the gif. If you need a video for something smoother, let me know. But this should give you an idea of the delay I have when I step through. Please note that the delay was never this severe. !
Thanks, I saw similar. It looks there is no longer a problem on the JS debugger side; it seems like vscode is being a bit slow to process things. For example, in the log, I see requests for stacktrace information come in for the previous event even after session has already been continued. Rob, might be a side-effect of the queuing a few iterations ago?
Just FYI, this is also a node.JS problem too. My example is only showing client side, but I work in Node all the time, and its the same problem.
Just checking for a status update on this issue.
<!-- AUTHORVERIFICATIONREQUEST --This bug has been fixed in the latest release of ! you can help us out by commenting if things are now working as expected.

If things still don't seem right, please ensure you're on version of Insiders (today's or later - you can use in the command palette to check), and leave a comment letting us know what isn't working as expected. Happy Coding!
Just as I was accepting that this debugger would always have latency issues, I get this notification today. I immediately installed Insiders, from someone who uses this style of debugging all the time, I can confirm this has been fixed! I will continue to test of course, but so far this is the fastest I've ever seen the step into debugger work, even before this had been a verifiable problem. Thanks for addressing this. As someone who debugs code 90% of the time, this was pleasant surprise to see fixed! /verified