Repository navigation
Very long delay when a breakpoint is hit and many (150+) threads are created by the program #9988
Description
Environment
- OS and version: Ubuntu 20.04.5 LTS
- VS Code: 1.72.1
- C/C++ extension: v1.12.4
- OS and version of remote machine (if applicable): gdbserver is running on an embedded ARMv7 Linux
- GDB version: 7.4
Bug Summary and Steps to Reproduce
Bug Summary:
I am developing a C application with 150+ threads and debug it remotely via gdbserver. When the first breakpoint is hit, vscode requests detailed information about every thread in the application and it takes about 3 minutes to complete. The debugging is very painful due to this.
The communication between gdb and gdbserver is very sensitive to the network latency. It is important to make as few requests to gdb/gdbserver as possible.
Steps to reproduce:
Create an app which starts 150+ threads.
Debug it remotely using gdbserver.
Set a breakpoint to be hit after all threads are created already.
Debug the program.
When the breakpoint is hit you will get a significant delay before vscode UI reports the breakpoint hit.
Debugger Configurations
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) Debug app",
"type": "cppdbg",
"request": "launch",
"program": "link.out",
"stopAtEntry": false,
"cwd": "${workspaceRoot}",
"environment": [],
"externalConsole": true,
"MIMode": "gdb",
"miDebuggerPath": "arm-linux-gnueabi-gdb",
"miDebuggerServerAddress": "10.0.1.10:9099",
"targetArchitecture": "arm",
"symbolLoadInfo": {
"loadAll": false
},
"logging": {
"engineLogging": false
},
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"text": "-interpreter-exec console \"set sysroot build_dir/sysroot\"",
"ignoreFailures": true
}
]
}
]
}Debugger Logs
Here is what happens when a break point is hit and why it takes so long.
The break point is hit:
1: (20384) ->=thread-created,id="2",group-id="i1"
1: (20384) ->~"[New Thread 1800]\n"
1: (20385) <-1023-thread-info 2
[New Thread 1800]
1: (20389) ->=breakpoint-modified,bkpt={number="3",type="breakpoint",disp="keep",enabled="y",addr="0x00b5efb4",func="x",file="x.c",fullname="x.c",line="568",times="1",original-location="x.c:568"}
1: (20390) ->~"[Switching to Thread 1800]\n"
[Switching to Thread 1800]
1: (20466) ->*stopped,reason="breakpoint-hit",disp="keep",bkptno="3",frame={addr="0x00b5efb4",func="x",args=[],file="x.c",fullname="x.c",line="568"},thread-id="2",stopped-threads="all",core="0"
Information about all(!) threads is requested:
1: (20467) <-1024-thread-info
While GDB executes the request above, it reports availability of new threads (158 in my case):
1: (20509) ->=thread-created,id="3",group-id="i1"
1: (20509) ->~"[New Thread 1639]\n"
1: (20509) ->=thread-created,id="4",group-id="i1"
1: (20509) ->~"[New Thread 1640]\n"
1: (20509) ->=thread-created,id="5",group-id="i1"
1: (20510) ->~"[New Thread 1641]\n"
vscode starts to request info about each reported thread. Even though information about all threads has been requested earlier:
1: (20510) <-1025-thread-info 3
1: (20510) ->=thread-created,id="6",group-id="i1"
1: (20510) ->~"[New Thread 1642]\n"
[New Thread 1639]
1: (20510) ->=thread-created,id="7",group-id="i1"
1: (20510) ->~"[New Thread 1649]\n"
1: (20510) ->=thread-created,id="8",group-id="i1"
...
...
1: (20528) <-1178-thread-info 156
[New Thread 1798]
1: (20528) <-1179-thread-info 157
[New Thread 1799]
1: (20528) <-1180-thread-info 158
[New Thread 1801]
1: (20528) 1023: elapsed time 143
1: (20528) Send Event AD7ThreadCreateEvent
...
Information about all 158 threads has been requested.
After 11 seconds GDB returns response to request -thread-info``` and starts to slowly return responses for individual thread info requests:
...
1: (31603) ->1024^done,threads=[{id="158",target-id="Thread 1801",frame={level="0",addr="0xb6e97798",func="??",args=[]},state="stopped",core="0"},{id="157",target-id="Thread 1799",frame={level="0",addr="0xb6fa7ce4",func="??",args=[]},state="stopped",core="0"}, ...
1: (31604) ->(gdb)
1: (31606) 1024: elapsed time 11138
1: (32457) ->1025^done,threads=[{id="3",target-id="Thread 1639",frame={level="0",addr="0xb6e91e7c",func="??",args=[]},state="stopped",core="0"}]
1: (32458) ->(gdb)
1: (32458) 1025: elapsed time 11948
1: (33343) ->1026^done,threads=[{id="4",target-id="Thread 1640",frame={level="0",addr="0xb6e97798",func="??",args=[]},state="stopped",core="0"}]
...
After 151 (!) seconds GDB responds to the last thread info request and vscode is almost ready to inform a user about the break point:
...
1: (171843) ->1180^done,threads=[{id="158",target-id="Thread 1801",frame={level="0",addr="0xb6e97798",func="??",args=[]},state="stopped",core="0"}]
1: (171843) ->(gdb)
1: (171844) 1180: elapsed time 151315
1: (171845) <-1181-stack-list-frames 0 1000
Conclusion: it is not needed to request individual thread info since all thread info is requested anyway and such combined request is executed much much faster compared to many individual requests.
Activity
reneparis commentedon Oct 13, 2022
You got my vote - got similar problems on our side.
olgapshen commentedon Oct 14, 2022
My vote
jaemzfleming commentedon Oct 24, 2022
you got my vote too, this is a horrible issue that makes vscode much less useful than it should be. We should be able to debug in a timely manner. I'm new to this group. Is there some formal mechanism I can use to show my vote?
rlivings39 commentedon Oct 27, 2022
+1 the C++ debugging performance is the major workflow pain our team and colleagues experience using VSCode as a C++ IDE. It gets so bad for me that I sometimes switch to command-line GDB or use GDB in Emacs. Everything else for C++ development in VSCode scales much better in my experience.
rcontinuum commentedon Oct 28, 2022
+1
gewa24 commentedon Nov 10, 2022
+1
muddle216 commentedon Nov 14, 2022
+1
martymcbro commentedon Dec 2, 2022
+1
krysgor commentedon Dec 2, 2022
+1
shaharh9110 commentedon Jan 17, 2023
+1
crazydef commentedon Jan 18, 2023
This has nothing to do with remote debugging. Performance when debugging locally is equally awful.
I have to wait minutes to get local variables to appear (during which time I can do nothing). Closing "locals" in the variables window does nothing because it's automatically reopened when execution next stops.
This effectively makes VSCode unfit for purpose and needs to be fixed.
timmeh87 commentedon Jan 23, 2023
+1 why should we have to disable everything just to step normally? Not very useful to me with everything hidden
er-mo commentedon Feb 14, 2023
+1 from me as well. Very important to have fast gdb on VSCode.
marcomeyerVFX commentedon Feb 19, 2023
+1 Just recently started debugging a project again after having it sit around for 2 years and this used to work quite decent and snappy. Now it's almost impossible to debug it at all, I wonder what was introduced in the meantime that caused this
Ubachris commentedon Feb 21, 2023
+1 I'm currently debugging a multi-threaded program (80+ threads) that takes a long time to step through the lines after hitting a breakpoint. It makes debugging with VS code a rather painful experience. I have no such performance issues when debugging with gdb on the command line
54 remaining items
carterols commentedon Oct 13, 2024
Georg Lauterbach (@georglauterbach) I haven't seen had that happen to me... I'm sorry! Maybe there's an LLDB setting you can try?
kyselejsyrecek commentedon Oct 13, 2024
I am afraid LLDB would not suit our use cases either with remote debugging using gdbserver and KGDB on ARM and ARM64 platforms with custom firmware.
yuriy-chumak commentedon Oct 14, 2024
kyselejsyrecek
Just a "./configure", nothing more.
Maybe these can help?
config.log:
gdb/config.log:
And a full gdb/config.h: config.zip
r1250gs commentedon Oct 14, 2024
Georg Lauterbach (@georglauterbach) Here is the GDB config in the VSCode project:
The
~/.gdbinitonly defines some customized pretty printers.vipcxj commentedon Oct 17, 2024
Yuriy (@yuriy-chumak) I came across this problem while using vscode in remote connection mode. Because my code is on linux and I work on windows. I'm not sure if this has anything to do with it.
carterols commentedon Oct 17, 2024
vipcxj same here. I do remote development.
kyselejsyrecek commentedon Oct 17, 2024
This issue is related to remote debugging using gdb and gdbserver.
blackworm27 commentedon Oct 22, 2024
I got here because C++ code stepping was extremely slow for me on a local executable using VSCode with cpptools and gdb. Hiding the "Variables" section of the "Run and Debug" sidebar tab made it faster, but obviously was not a solution. Examining the
logging/engineLogginglogs found many variable lookups taking 0ms, and many others taking 200-400ms each.After much searching and pain, I found that adding the GCC compiler flag
-femit-class-debug-alwaysfixed it for me. Documentation and caveats for the flag are here: https://gcc.gnu.org/onlinedocs/gcc/Debugging-Options.htmlI am using CMake; here is my entry in my CMakePresets.json file.
{ "name": "debug", "inherits": "default", "displayName": "Debug", "description": "Configure debug build", "cacheVariables": { "CMAKE_BUILD_TYPE": "Debug", "CMAKE_CXX_FLAGS_DEBUG": "-O0 -g3 -femit-class-debug-always -fno-merge-debug-strings" } }Incidentally, this same flag fixed a problem I had trying to switch to using lldb (with the CodeLLDB vscode extension), where lldb was not able to inspect any class members. I had tried to switch to lldb because of the vscode/gdb issue, but to my amazement found that the flag fixed the original issue.
I hope this can help anyone with a similar problem. I am using g++ 12.3 with gdb 12.1, vscode 1.91.1, cpptools v1.22.10 on Ubuntu 22.04. I'm unsure if it is relevant, but I am using an RPATH with $ORIGIN (in CMake: CMAKE_BUILD_RPATH_USE_ORIGIN).
kurts-gmail commentedon Nov 5, 2024
Thank you! This solved the issue for me. Reduced the step time from 10s to instantaneous.
carterols commentedon Nov 6, 2024
This didn't totally fix it for me. I'm still seeing the same issue when debugging an app with around 35 threads. Hitting the initial breakpoint in a function took around 30 seconds to load the "locals" variables. Stepping seemed to be better though, but still not as fast as LLDB through the CodeLLDB extension. Feels very slow when stepping, although I am using a natvis file to display Qt types.
My setup is GCC 11.4 and GDB 15.1.
zyrkiel commentedon Dec 5, 2024
Using lldb instead of gdb was one workaround for me, but I wasn't satisfied with it.
Finally, I have succeed to fix this issue by moving my vcpkg folder out of my vscode workspace folder. This also fix my auto-completion lag, my "got to declaration" lag and my "go to definition" lag.
jpvbarbosa commentedon Dec 17, 2024
An interesting discovery: not setting
solib-absolute-prefixand/orsysrootto local library paths seems to have resolved the issues we were facing when remote debugging.I noticed the original poster is also calling
set sysroot <local dir>in his launch config whereas commenters who are reporting no issues on their end don't have it present in their configs.Completely contradictory since using the local library files should be much more performant than reading from the remote, but luckily it works for our use case.
Now why VSCode struggles with local sysroot and library paths, I have no idea. Other IDE's and command line GDB handles this without issue. I did notice, however, that the Native Debug extension also experiences massive slowdowns with a local sysroot, so whatever issue we were facing seems to be VSCode-wide, rather than isolated to the cpptools extension.
senyai commentedon May 1, 2025
Pretty printers can significantly slow down the debugging experience. Try disabling pretty printers to see if it improves performance:
-exec disable pretty-printergeorglauterbach commentedon May 2, 2025
What about the variable formatting in VS Code with pretty printers disabled? Will you still be able to inspect them properly? Disabling PP would be of no use if variables became unreadable.
AbhiramNS1 commentedon Aug 13, 2025
This issue still exits . Why are they not considering to solve this issue . Atleast provide a feature to control the request send out by the extention . Currently the extention is sending stack traces 0 - 1000 of depth . Atleat provide a felxible method to reduce the depth .
I just cross compiled by gdbserver
GNU gdbserver (GDB) 17.0.50.20250813-git
Copyright (C) 2024 Free Software Foundation, Inc.
gdbserver is free software, covered by the GNU General Public License.
This gdbserver was configured as "arm-linux-gnueabihf"
This is taking about 10 seconds for next command press . With around 8 threads in parallel . Its too slow . The majority of the waiting comes from the request for stack frames from the extenstion .