5 ms·
Maybe this is the right forum to ask... Why the debug system in Julia is so terribly slow? It seems to me that Debug.jl (or whatever runs in VSCode) interprets,
by sharikous 5y ago
Maybe this is the right forum to ask... Why the debug system in Julia is so terribly slow? It seems to me that Debug.jl (or whatever runs in VSCode) interprets, rather than running, the code. The result is that for me debugging is just unusable.
The standard way to put breakpoints in an executable is to replace the instruction at which to stop with INT3 (or something analogous in other architectures). Then give the system a callback for your debugger when the CPU receives the interrupt.
Is there a way to make Julia's debugger do that?
- simeonschaub 5y agoYes, it uses Debugger.jl, which relies on JuliaInterpreter.jl under the hood, so while you can tell the debugger to compile functions in certain modules, it will mostly interpret your code. You might be interested in https://github.com/JuliaDebug/Infiltrator.jl https://github.com/JuliaDebug/Infiltrator.jl, which uses an approach more similar to what you describe.
- adgjlsfhk1 5y agoThe other part of the answer is that currently JuliaInterpreter is really slow because it is a very naive interpreter. Speeding it up by a factor of 5 or so should be relatively easy if anyone wants to try.
- simeonschaub 5y agoI would not go as far as calling it very naive, there has certainly been some work put into optimizing performance within the current design. There are probably some gains to be had by using a different storage format for the IR though as proposed in [1], but it is difficult to say how much of a difference that will make in practice. [1] https://github.com/JuliaDebug/JuliaInterpreter.jl/pull/309 https://github.com/JuliaDebug/JuliaInterpreter.jl/pull/309
- KenoFischer 5y agoWe had a debugger like that a few years ago, but the experience was unsatisfying for people, because you got the "debugging optimized C++ code" experience with unreliable breakpoints and mostly unavailable debug variables. I took the decision to scrap that and instead put out something simple that's slow but robust and reliable. The plan was always to then use the JIT on top of that to create a "debug-specialized" (using statepoints for local variables rather than DWARF) version of the running code, which should give you perfect debuggability at minimal runtime cost, but it's a fair amount of work that nobody has wanted to do yet. In general, traditional debugging has always taken a bit of a backseat in Julia, because people code is usually decently functional, so they just run it in a Revise loop and write their state dumps directly into the code (you could deride that that printf debugging, but I think it has a bit of a bad rap, particularly in a live-reloading system, where you basically get an execution log of your revising expression on every file update). There are still cases where a traditional debugger is useful, so I'm hoping someone will take that on at some point, but so far there've been higher priorities eleswhere. Also do note that you can switch the debugger into compiled mode, which will be faster, but ignore breakpoints.
- Tarrosion 5y agoThanks for this explanation. One thing I've never quite grokked: if the debugger ignores breakpoints in compiled mode, how is running in debug compiled mode different than just...running the code normally?
- adgjlsfhk1 5y agoThe problem is that when you compile code you can have things like constant propagation make it so that your breakpoint just isn't in the compiled code. Finding the right balance to make it look like your code is running the way you expect is really hard.
- simeonschaub 5y ago> how is running in debug compiled mode different than just...running the code normally? It's not. By default, the debugger will recursively interpret any nested function calls until it encounters any intrinsics, since breakpoints can be set inside any functions. Compiled mode means the debugger won't do that for functions in a certain module (e.g. Base) and instead invoke the function like you normally would, so breakpoints either inside those functions or -- if functions from other modules are called from inside the compiled functions -- also breakpoints inside those will be ignored.
- arksingrad 5y agoI'm similarly disappointed in Debugger.jl, but I find that Infiltrator.jl often helps me get where I need to go for intra-function problems.