Time travel is great for understanding someone else's large program, so that you can see where it goes as it is running. In large projects the instruction pointer is hop around madly throughout the code, and seeing where it goes like the path of a bird is rather handy.
What a good debugger can do
191–200 of 208 posts
Re: What a good debugger can do
#192Earlier quoted context omitted.
Great comment. Since it sounds like your jam, do you have any suggestions for reading on logging best practices in this context?
Hmm, I don't have much in the way of links; but I can brain-dump some of my accrued personal opinions, for what they're worth: * Relatively early in your project, incorporate a "real" logging system, and start leaning on it. For me, in C++, I have most recently been using 'spdlog'[1] fairly happily. It accumulates data in memory and dumps it from a dedicated logging thread at a configurable frequency. That approach h…
Always enjoy reading people enthusing about tooling they know well.
Re: What a good debugger can do
#193Earlier quoted context omitted.
> But his main point is that debuggers distract developers from seeing the problem as a whole rather than just understanding what's going on the vicinity of that problematic line. So, the debugger incentivises small, targeted fixes rather than bigger solutions for more systematic problems. Said differently by other old beards in this classic of Ken Thompson & Rob Pike: https://www.informit.com/articles/article.aspx?p…
That could work in the old Unix days, and for toy problems today. But if Firefox crashes you can't just build a mental model of 10M lines of code and intuit the problem.
Re: What a good debugger can do
#194There should be debuggers for interpreted dynamic languages that can be scripted with strict type systems. Possibly like eg prolog; like if I have Python code that has a Person class defined in it, I could just check for invariant violations with the debugger, eg check self.parent != self.child and whatnot. Then if I come up with a nice check while debugging I should be able to save that as a unit test for the projec…
we have pretty magnificent tools for the mapping to a shared semantics of syntax-
tree-sitter :: any syntax -> 1 semantics
- we have tree-sitter, lsp, etc; any language can be added with an easy description.But we don't have great tools for mapping (1 semantics -> any syntax) - in some sense, the inverse of tree-sitter:
inverse-tree-sitter :: 1 semantics -> any syntax
If we did, we could have a universal any language meta-debugger library.The key impact of this is that anybody from some individual language could add a plugin, which could apply to every supported language that uses the subset of features that apply to that plugin.
Think about the network effects of a language which has a large universe of plugins - now think about the even greater network effects if it could be a union of supported languages - that's strictly at least as good, if not vastly more network-effectful. So I think the benefit to people would increase rapidly if people contributed to it across many different languages, so it could be a good collaborative tool.
I bring this up under this discussion because the debugger would be the exact best place to apply something like the inverse of tree-sitter
pretend I'm not ignoring this would likely lead to a strangely organized library with lots of potential spots of inter-language interface annoyances, so it would not probably be strictly better... :)
Re: What a good debugger can do
#195Earlier quoted context omitted.
>can step through the code backward and rewind the program state to any point in history This seems impossible for anything that modifies external state. Say 1. Open database connection 2. Commit data 3. Close database connection How would you rewind right before #2 if you've already completed step #3? You'd need the socket/connection you already closed Unless that means something more like "keep a running record of…
My guess is that you could attempt something like this by recording system calls as your program executes and then replay them in whichever order you need. You would need a lot of storage space for some programs, but in simple cases that might still be useful. So, in your example, playing the program back wouldn't really try to read from a closed socket, it would just hit debugger's database of stored system calls at…
I am a co-founder of undo.io, many of our customers do this.
It's not as bad as it first sounds because the replay of the program will modify itself deterministically. (Though as always with this stuff, there are some gotchas.)
Re: What a good debugger can do
#196Earlier quoted context omitted.
>can step through the code backward and rewind the program state to any point in history This seems impossible for anything that modifies external state. Say 1. Open database connection 2. Commit data 3. Close database connection How would you rewind right before #2 if you've already completed step #3? You'd need the socket/connection you already closed Unless that means something more like "keep a running record of…
Yes, that's what it means. Ideally you'd record the state of memory and CPU after each instruction. In practice you can take snapshots at regular intervals and hook system functions to record their inputs and outputs. If a call has to be replayed the debugger intercepts it and gives the debuggee a recorded result.
Re: What a good debugger can do
#197a good debugger supports different kinds of breakpoints, offers rich data visualization capabilities, has a REPL for executing expressions, can show the dependencies between threads and control their execution, can pick up changes in the source code and apply them without restarting the program, can step through the code backward and rewind the program state to any point in history, and can even record the entire pro…
Which of these can't visual studio or intellij do?
Re: What a good debugger can do
#198Earlier quoted context omitted.
That sort of argument is somewhat defensible in a context like the kernel, where when things go haywire, you can't really expect there to be enough sanity to have a debugger work. But very little code runs in such a context, and it turns out that a well-written debugger has incredible features. Also, Linus is writing this 22 and a half years ago, where the capabilities of debuggers were... far, far less. Time-travell…
> Time-travelling debuggers is really a game changer Core dumps have existed forever. They give you a stack trace and register values at the time of crash. Even better, you don't need a debugger running at the time of crash and you can dig into dumps sent from nontechnical users. Sure, Bret Victor's demo was cool. But time travel debugging is so completely oversold at this point that I can't take anyone seriously tha…
With a time travel recording I can put a watchpoint (aka data breakpoint) on the state that is supposedly impossible, and reverse-continue back to see exactly where it got set. (And repeat as required.) It really is very powerful.
Admittedly there are situations in which it's not practical to get a recording, but when you can... almost any bug becomes trivial.
Re: What a good debugger can do
#199Earlier quoted context omitted.
Pycharm/Intellij stuff does everything you mention in a fairly simple GUI that doesn't make you understand how to set conditional variables, but encourages you to realize you want to
do you know if it's possible to step back in pycharm/intellij? the article mentions some debuggers having this ability, but i never saw an option in pycharm. learning how to undo my last step would save so much time. right now, i have to anticipate a risky step and run that line in the debugger console.
I don't think there is a solution for PyCharm.
Re: What a good debugger can do
#200Earlier quoted context omitted.
Depends what functionality you think "a time-traveling debugger" must provide, Smalltalk implementations usually provide something like this: https://cuis-smalltalk.github.io/TheCuisBook/The-Debugger.ht...
To qualify as "time-travelling" You should at a minimum be able to step and run backwards and inspect the values of variables at a previous point in time. Ideally all debug features (breakpoints, watchpoints, tracepoints &c.) will work running both forwards and backwards. To meet the standard of the "perfect debugger" from the TFA intro, I would say you should be able to run backwards, modify a function, and run forw…
"The stack of (framed) execution contexts gives a history of the computation so far. You can select any frame, view instance values in the receiver, view the arguments and method variables at that point."
So step backwards, modify a method, step backwards before that method send, and resume execution with the modified method. (Note: resume rather than restart, so the modified method has the preserved context unless we manually edit that context.)