3 ms·
> you don't need a special debug build to be able to debug Note that this is highly dependent on choice of compiler. Clang is utter crap for debugging even at
by o11c 2y ago
> you don't need a special debug build to be able to debug
Note that this is highly dependent on choice of compiler. Clang is utter crap for debugging even at -O1, but I've encountered basically no trouble ever using GCC at -O2 (you do have to learn a little about how the binary changes but that's easy enough to pick up). I really would not recommend -O3; historically it introduced bugs and regardless it makes the build process much slower, and the performance gain is fairly negligible (I can't say how much it destroys debuggability due to lack of experience). I can't speak for MSVC personally but it's a bad sign that its culture strongly promotes separate debug builds.
That said, sanitizers are a place where a special debug build does help. Valgrind can do many of the things that sanitizers can but is around 10× slower which is a real pain if you can't isolate what you're targeting, so recompiling for sanitizers is a good idea.
(Other brief notes)
I have never actually encountered a case where the lack of frame pointers actually caused problems. As far as I'm concerned, any tool that breaks without them is a broken tool. (Theoretically they can speed up large traceback contexts if you're doing extensive profiling; good API design probably helps for the sanitizers case here)
Rather than assembly int3, Unix-portable `SIGTRAP` is very useful for breakpoints; debuggers handle it specially. You can ignore it for non-debugged runs but get breakpoints when you are debugging without changing the binary or options! Alternatively you could leave it unignored if you have tooling that dumps core or something nicely for you.
- omoikane 2y agoDebugging experience aside, I found that "-O3" is generally worth it if you also set "-march=native". For example, here are some run times for computing SHA256, you can see that there is slightly more to be gained going from -O2 to -O3 with -march=native: -O2: 10.22 -O3: 9.82 -O2 -march=native: 9.86 -O3 -march=native: 9.43 This is basically SHA256 over ~8GB of data, averaged over 5 runs. The numbers are rather crude here since I measured them just now, but I remember it was more significant when I first did it last month for https://news.ycombinator.com/item?id=40687942 https://news.ycombinator.com/item?id=40687942
- josephg 2y agoYeah -march=native is amazing. I use it when compiling & benchmarking rust code. But - to anyone reading this later - please don’t do this blindly. You probably never want to distribute binaries with this flag set. It enables all the features available on the host CPU. So your build will change depending on the physical cpu you have installed. If you have a modern amd cpu, it may enable avx512 extensions and make your binary unusable on many Intel CPUs.
- rerdavies 2y agoUnpleasantly, GCC is utter crap for debugging even at -O0 on ARM64 platforms. I've tried both -O0 and -Og. :-( Highly unpredictable step-over behaviour, and many genuine lines of code that won't take breakpoints.... MSVC has always been immaculately good at debugging, so this is an unpleasant surprise that's seriously cutting into my productivity. I've always felt that the debug code performance penalty was a good proxy for simulating what what users experience on machines that aren't god-level development machines. If it doesn't perform nicely on my machine with -O0, it's not likely to perform well on machines owned by mere mortals. And there's the extra lovely reward of being pleasantly surprised the snappy lively responsiveness of code that's compiled with -O3. (Optimizing actually-performance-critical code is of course, a separate kettle of fish).
- mgaunard 2y ago-O3 only breaks your code if it is invalid to begin with.
- account42 2y agoGenerally true, but compiler bugs do happen. Still, it's better long-term to report them than spreading FUD about -O3.
- o11c 2y agoIn theory. In practice, it's not as widely tested and so a lot more bugs survive. This search is approximate both ways, but still finds a lot of examples of O3 being outright broken: https://gcc.gnu.org/bugzilla/buglist.cgi?short_desc=O3&resolution=---&resolution=FIXED&order=Importance&query_format=advanced&bug_status=ASSIGNED&bug_status=RESOLVED&bug_status=VERIFIED&short_desc_type=allwordssubstr&cf_known_to_work_type=allwords&cf_known_to_fail_type=allwords https://gcc.gnu.org/bugzilla/buglist.cgi?short_desc=O3&resol...
- mgaunard 2y agoMost of those bugs are about crashes during compilation or compilation being slow, and also this is 30 years worth of bugs. Of note, most of those (few) bugs tend to be related to specific language extensions.