Overview
Refactoring lldb-dap
server mode to allow multiple DAP connections in order to improve symbol caching to improve launch and attach performance.
Background
lldb-dap
supports listening on a port for a DAP connection, however this only accepts the first connection and then the process stops. This means we cannot have an lldb-dap
process reused for multiple debug sessions.
When launching or attaching to a process one of the steps that must be taken by the debugger is to load symbols for both the binary itself and any runtime linked libraries that are associated with the binary. On an M1 Max MacBook Pro this can take approximately 12s for a small “Hello World” style iOS application. This majority of the time is spent loading symbols, only around ~0.5s of the time spent was performing the attach.
By refactoring lldb-dap
to have a server mode we can take advantage of the persistence of the server to cache symbols and improve debugger performance between debug sessions.
Architecture
lldb is architected to allow multiple debug sessions today. The SBDebugger
instance represents a single instance of a debug session. In order to support multiple debug sessions on the same server we will need to refactor lldb-dap
to not have a single global lldb_dap::DAP g_dap
object and by extension SBDebugger
instance. Instead, when a connection is made to the server we should create a new lldb_dap::DAP
instance that is associated with that specific connection.
A number of helpers and utilities will need to either be redesigned or perhaps moved to accommodate the removal of the g_dap instance.
lldb/tools/lldb-dap/JSONUtils.{h,cpp} - In general these should be abstracted to have parameters for any fields the access from the g_dap
instance.
lldb/tools/lldb-dap/LLDBUtils.{h,cpp} - This set of functions depends on the lldb_dap::DAP
instance to execute an lldb operations. In general, these functions should take a lldb_dap::DAP &dap
parameter.
lldb/tools/lldb-dap/DAP.{h,cpp} - The lldb_dap::DAP
object should be updated to ensure it is destructible and correctly cleans up any open file handles it creates while running.
lldb/tools/lldb-dap/lldb-dap.cpp - Request handles should take a lldb_dap::DAP&
value as a parameter, so they can be specific to correct connection.
Threading model
- The main thread is listening and accepting connections
- Each connection will have a thread for the
lldb_dap::DAP::loop()
, a thread forEventThreadFunction
and a thread forProgressEventThreadFunction
.
Process Management
With this change, we should be able to start the lldb-dap
in a server mode and use the same instance until VS Code is closed. We could add a command to stop the running process, since it can end using a lot of memory for the symbol caches.