When I start
lldb I have to wait about 15 seconds (on a 2020 MacBook Pro) while it says “Parsing symbol table for [library]”. The [library] part keeps changing quickly. My program is not that big, and it looks like most of the names flying by are Apple frameworks. Is there a way to do this lazily, or otherwise avoid the startup delay?
When I start
There is On Demand Symbols — The LLDB Debugger, this was added in lldb 15 though so if you have an Apple provided lldb it may not be present.
This is controlled by a setting
symbols.load-on-demand (and FYI you can search commands and settings by doing
If you able to use a newer copy of lldb, there are prebuilt binaries here Release LLVM 15.0.1 · llvm/llvm-project · GitHub for arm64 and x86_64.
You could also check the setting
symbols.enable-external-lookup. I don’t know if it’s doing anything in your case but worth a go disabling it if it is on by default.
Thanks, I will try that. I am able to use version 15. Which file in that release directory has a pre-built binary for lldb? I see the lldb src package, and I downloaded clang+llvm which has binaries but not lldb.
Sorry yes, some packages don’t include lldb and some do (despite the naming). We (Linaro) include it on Linux so I just assumed.
You could download the source code and build it yourself Building — The LLDB Debugger. Your system clang should be fine as the compiler for doing that.
Source as in https://github.com/llvm/llvm-project/archive/refs/tags/llvmorg-15.0.1.zip or you could checkout llvm-project from github if you want the very latest.
I finally got around to trying this out and it doesn’t seem to work. I have lldb 15.0.1 built from the source package here: Release LLVM 15.0.1 · llvm/llvm-project · GitHub
I put the setting in
~/.lldbinit and also tried it in the session:
> ~/Dev/lldb-15.0.1.src/build/bin/lldb (lldb) settings set symbols.load-on-demand true (lldb) target create ./build-debug/MyApp/MyApp.app/Contents/MacOS/MyApp [spends time here 'Parsing symbol table' for tons of things] Current executable set to '/..../MyApp' (x86_64).
I don’t know enough to say if it should help here.
I think @jeffreytan81 was the author of the feature, perhaps they can help?
DavidSpickett, thanks for including me in this. @RobNik, symbol on-demand is designed to on-demand index debug info on Linux (Mac already has accelerator table so won’t help either) not symbol table. Since your slowness comes from symbol table it won’t help.
But you can try clayborg’s symbol index cache feature instead. It would cache the symbol table in consumed format to disk so that incremental debug sessions would be faster. You can enable by adding
-O "settings set symbols.enable-lldb-index-cache true" from command line.
It has two issues though:
- It won’t improve for the first debug session. (Actually would be worse because of extra time to write into cache).
- Changing binary would invalidate the caching. This would be especially bad if your app is using static linking mode which merges a number of modules into a gagantic module.
For future, I had some thought to on-demand load symbol table – allow users to specify a white list modules to load symbol tables instead of parsing everything. That might cause some stack unwinding or symbolic/function breakpoint feature to be not working but with the gain of much faster performance. I think this is a fine trade-off considering Windows debuggers (vsdbg and windbg) does this all the time.
Curious to hear the thoughts from, @labath, jingham and clayborg.
Sorry, only allowed to tag two persons…
Thanks, I will look into this.
I’m developing on macOS, but I’m off the beaten path, so I may be doing something wrong. In the past I used Xcode, and I while I had problems with LLDB seeing symbols I never remember it taking this long to start. Now I’m using Emacs, CLion, and CMake, to build the C++ code, and running the debugger from the command line. I’m learning more about how things work, but I may being doing something abnormal in my build.
Anyway, I’ll report back if I make some progress.
Jeffrey, I think symbol table load filter (maybe with regex) is a great feature for speed up symbol loading, especially for large projects e.g. chromium. In my personal dev experience, mostly I only care about symbols / breakpoints / stack unwinds in a few .so files.
We added a symbol loading allow list way back in the day when we were trying to get gdb w. stabs vrs. the burgeoning MacOS X to work at all well. It did help with that, but people really didn’t enjoy having to manually manage their symbol world, so we ended up adding a bunch of heuristics (e.g. if a library appears in a backtrace, or is explicitly mentioned in a breakpoint, we auto-read it in). Even then the experience was only so-so, and when we started using DWARF things got enough faster that we dropped it with a sigh of relief.
It seems to me that the debugger spends most of its time idle waiting for something to happen, and we should take advantage of that. So a better long term approach would be to read in symbols in the background, maybe with a “get these ones immediately” list to kick things off.