Performance issue when stepping through a deep callstack
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 30/100
- Issue type
- Bug
- Clarity
- Mostly clear
- Activity status
- Stale
- Domain
- devtools, performance
Research direction
Start at ext/debug/debug.c lines 92-98 and inspect how rb_make_backtrace is used while stepping through a deep callstack. Compare the proposed rb_threadptr_backtrace_object and debase approaches, including their *_core.h requirements. Done means stepping through roughly 150 calls no longer incurs the reported slowdown and memory pressure.
Written by the indexing model from the issue text.
Description
Your environment
ruby -v: 2.7.2p137rdbg -v: 1.6.2
Describe the bug
When stepping through with a deep callstack, the debugger becomes slower with each step.
To Reproduce
In a codebase which has a method that's ~150 calls deep in the stack, add a breakpoint, debug, and step through.
Expected behavior
It wouldn't be slow
Additional context
We are facing this issue at Stripe, and we tracked down the problem to: https://github.com/ruby/debug/blob/296daa6742e114395a4ce336b8721d48a6e5e52f/ext/debug/debug.c#L92-L98
This seems to be generating the full backtrace through rb_make_backtrace, just to then take the size. rb_make_backtrace (source) generates an array of strings each time it's called. Those strings end up not being used, and after a couple of iterations, you end up with a big memory footprint, which causes the GC to collect them, significantly slowing down the debugger.
Luckily, it looks like you are already aware that this is inefficient (given the // TODO: more efficient API) :)
Looking into alternatives, I came up with a couple of options (but open to any other ideas):
- Use
rb_threadptr_backtrace_objectto skip the formatting of the backtrace, saving some extra memory (but still generating more than necessary) debasesolves this with a different approach: https://github.com/ruby-debug/debase/blob/5780803819f16190ce50ddfdad5775acf8f95fd1/ext/hacks.h#L26
Both of them, though, require the inclusion of *_core.h, which is not currently possible (debase solves it by using its own version of ruby_core_source)
- Dominant language
- Ruby
- Stars
- 1.3k
- Forks
- 146
- PR merge metrics
- No merged PRs in 30d
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from ruby/debug
-
Difficulty 3/5 1-2 days Newbie friendliness 68/100
-
Support exceptionOptions in setExceptionBreakpoints to catch arbitrary exception classes via DAP Open
Difficulty 4/5 3-5 days Newbie friendliness 55/100
-
Difficulty 3/5 1-2 days Newbie friendliness 45/100
-
Difficulty 4/5 3-5 days Newbie friendliness 52/100
-
Difficulty 4/5 3-5 days Newbie friendliness 35/100
Similar issues
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
notch8/utk_knapsack#148 ·
-
feature
Difficulty 2/5 1-3 hours Newbie friendliness 64/100
betagouv/acces-cible#722 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
foobara/empty-ruby-project-generator#10 · 2 comments ·
-
Difficulty 1/5 Under an hour Newbie friendliness 90/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 88/100