Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I agree that debugging in Common Lisp is much more powerful than debugging in GDB. For one thing, when you get a condition and your repl enters the debugger, you immediately learn what condition handler you should add to your code so that it can automatically handle this case gracefully in the future. And you have the full compiler available to you in that repl, so you can redefine functions, change variables, and so on. This lets you recover from the error and leave the program running and in a better state than it was before you started. This is actually a super power that you just don't have when you're debugging a program written in C. (Technically I suppose some IDEs have an edit-and-continue feature, but I've never heard of anyone using it to save a program running in production.)

On the other hand, rr gives you a different set of features. You can rewind the full state of the program to any previous point in time. I've used rr a lot, and this capability is extremely useful. It makes debugging heap corruption, buffer overflows, use-after-free, and many other complicated bugs much, much easier. You just set a watchpoint on the data that was overwritten, then run the program in reverse (using the reverse-continue command) until it gets back to the point where the write happened. It really is like having a super power, but it's a different kind of super power than the Common Lisp repl.

Pernosco is another level above that. Instead of presenting you with the state of the program at a single moment in time and letting you run it backwards and forwards, it lets you query the full state of the program. Where before you would set a watchpoint and run backwards until you got to the previous write, with Pernosco you click on the value and it presents you with a list of _all_ writes to _all_ locations in the chain that leads to that value. For example, you can see that the value was written to the memory location from a register, and that before that it was read from some other memory location into the register, etc. It's really very cool.

There's no reason why a Common Lisp or Smalltalk runtime couldn't have these features in addition to a proper repl.



I have dumb question

> You can rewind the full state of the program to any previous point in time

Where does all this saved state go? I'm running a game that runs at 60fps, every frame 10s of megs of data change. It won't take more than a few second to run out of memory to save all the state. Further, if the game doesn't run at 60fps (or 90fps on VR) it's not usable, if saving this state slows the game down to 20fps or 15fps I can't tell if my code is working since the entire goal is to run at speed and check it all feels good.

Is there some technique these kinds of tools use to make it possible to do keep all changed state in this type of app or do they only work for some other type of app?


By capturing all external inputs to application, it can replay it many times and results will be always identical.

https://arxiv.org/pdf/1705.05937


It's a good question. rr writes all the state to disk. Every syscall of any kind gets saved and replayed back the same way when you replay the recording. This means that if your program reads a network packet in the recording, during the replay it will read exactly the same network packet at exactly the same point in it's execution.

On the other hand, outputs are not really recorded. During the replay your program will generate exactly the same output, so saving it to disk isn't necessary.

See http://rr-project.org/ for all the details.

There's no such thing as a free lunch, so it'll certainly slow your game down a bit. I recommend saving the trace to the fastest disk you can find. Also, you would want to run your game during development both with and without rr, precisely so that you know that you're not exceeding your time budget.


It's just a pity that it's on the "If you have to ask, you can't afford it" level of expense.

I'd like to try Pernosco, but we don't use it at work. There's no way I could afford it for my open-source projects, and I can't lobby for it without first trying it.


I'm fairly certain that they're working towards letting anyone sign up to use it. Of course I've no idea what the pricing will actually look like once they get there, but I doubt it will be that bad.

The real expense is in integrating with lots of different environments; Roc mentioned that integrations with Github and Travis were already working, but not Gitlab yet. (On the other hand you can do without any integration at all. Take a look at https://github.com/Pernosco/pernosco-submit/; it will upload the source from your computer to your debugging session if it's not cloned from a recognized git/hg host.)


You can try it out right now here: https://pernos.co/debug/e9UFXkGq__8KQB-N6n59lA/index.html https://www.youtube.com/watch?v=LR0pms_mQuY

We definitely are not aiming for "If you have to ask, you can't afford it".


Good to hear.

I could pay a bit for personal use, and hopefully it'd still be useful without integrations etc; I don't think I could ask anyone else I'm working with (open-source wise) to do that.


Thats what I like about lisp environments, and sadly after trying out Clojure, it can do no such thing (as of the time I tried it, about a year and a half ago), continuing at point 9f exception after allowing the user to change state interactively.


Clojure is heavily dependent on the host (JVM, JS) for such things, vs. a Scheme like Racket which is ground-up Lisp, or even a naive s-expr interpreter, which allow greater flexibility in this area.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: