nvim-dap-ui icon indicating copy to clipboard operation
nvim-dap-ui copied to clipboard

Horrible performance when debugging with `lldb-dap`

Open tmillr opened this issue 9 months ago • 5 comments

When I have the ui opened and step, ~50% of the time I have to wait anywhere from 10-30 seconds before the next line is hit and my programs stops. The latency makes it nearly impossible to debug. It goes back to nearly instantaneous (as expected) when I disable this plugin.

Last time I debugged Lua (single thread) I did not have this issue; the binary I'm debugging now runs 2 threads by default. Maybe it has something to do with debugging a decent sized binary, or maybe because there's multiple threads, idk.

Idk what the cause is, I just know that it involves this plugin. I have dap virtual text disabled, disabled all of my own custom hooks/listeners, etc. and I am not even doing anything in the UI but having it open.

With this plugin enabled

https://github.com/user-attachments/assets/be860850-e4b7-4501-adc4-e948dfe711bf

With this plugin disabled

https://github.com/user-attachments/assets/d9cf969f-9ab4-46dc-9195-1a57edfa7a73


Might be related to #429.

tmillr avatar Mar 17 '25 09:03 tmillr

Just to confirm: I too have this issue. Performance debugging C++ is terribly slow. I'm testing with a simple C++ file. I have just finished a complete update of neovim and encountered this issue. As suggested by https://github.com/rcarriga/nvim-dap-ui/issues/429 I've reverted to b726700 and this has cured the performance issue. (Actually this is prior to 055be38 )

I'll happily do some testing, forward configs or logs etc if it'll be of any help.

TBPLtd avatar Mar 19 '25 21:03 TBPLtd

I too have this issue. Performance debugging C++ is terribly slow. I'm testing with a simple C++ file.

Is your application multi-threaded?

tmillr avatar Mar 23 '25 02:03 tmillr

No, not multi-threaded. Not much more than 'hello world' - just uses std fstream, memory, vector to test out debugging.

TBPLtd avatar Mar 26 '25 15:03 TBPLtd

@TBPLtd could you please confirm once again which commit did you revert? It was https://github.com/rcarriga/nvim-dap-ui/commit/b7267003ba4dd860350be86f75b9d9ea287cedca (and NOT https://github.com/rcarriga/nvim-dap-ui/commit/055be38c3653923d1d3e0f155a50871545740798) ?

I just want to confirm, if this is the same performance issue as the one mentioned in https://github.com/rcarriga/nvim-dap-ui/issues/429 or not.

I'm responsible for https://github.com/rcarriga/nvim-dap-ui/commit/055be38c3653923d1d3e0f155a50871545740798 but it was a line-by-line revert to old functionality, nothing new really. This fixed a regression preventing multi-threaded callstacks from appearing which was broken for over half a year (https://github.com/rcarriga/nvim-dap-ui/issues/387). Afterwards, people started discovering issues that were blocked/hidden for the time period, and blaming my commit for it, but I have a felling those are just re-appearing old issues (e.g. https://github.com/rcarriga/nvim-dap-ui/issues/418).

sleeptightAnsiC avatar Jul 02 '25 22:07 sleeptightAnsiC

@tmillr

Does the patch mentioned in https://github.com/rcarriga/nvim-dap-ui/issues/429#issuecomment-2629181582 help in any way?

[hacky patch with async stackTrace request and caching]

diff --git a/lua/dapui/components/frames.lua b/lua/dapui/components/frames.lua
index eafe65b..5104e51 100644
--- a/lua/dapui/components/frames.lua
+++ b/lua/dapui/components/frames.lua
@@ -1,5 +1,7 @@
 local config = require("dapui.config")
 local util = require("dapui.util")
+local nio = require("nio")
+local dapui = require("dapui")
 
 ---@param client dapui.DAPClient
 return function(client, send_ready)
@@ -7,6 +9,11 @@ return function(client, send_ready)
   client.listen.terminated(send_ready)
   client.listen.exited(send_ready)
   client.listen.disconnect(send_ready)
+  client.listen.stopped(function()
+    for _,thread in pairs(client.session.threads) do
+      thread.frames = nil
+    end
+  end)
 
   return {
     ---@async
@@ -24,10 +31,18 @@ return function(client, send_ready)
         return
       end
 
-      local frames = threads[thread_id].frames
-      if not frames then
-        local success, response = pcall(client.request.stackTrace, { threadId = thread_id })
-        frames = success and response.stackFrames
+      local thread = threads[thread_id]
+      local frames = thread.frames or thread.frames
+
+      if not frames and not thread.frames_worker then
+        thread.frames_worker = nio.run(function()
+          local success, response = pcall(client.request.stackTrace, { threadId = thread_id })
+          if success and response.stackFrames then
+            thread.frames = response.stackFrames
+            dapui.elements["stacks"].render()
+          end
+          thread.frames_worker = nil
+        end)
       end
       if not frames then
         return

sleeptightAnsiC avatar Jul 02 '25 22:07 sleeptightAnsiC