Realistic scenario that gamedev uses: deoptimize translation units you are interested in finding or reproducing bugs.
Yep, looks like that’s this bullet point:
https://dhashe.com/category/blog.html#partition-your-tus-int...
This would be really unusual though right? For reference, in plain C code I see a 2x slowdown, in Zig a 4x slowdown (which I still need to investigate why exactly that's the case), and in C++ (even with heavy stdlib usage and on MSVC) at most 10x - which is the absolute worst case I've seen yet. My C++ info is a bit outdated though, have things gotten much worse in "modern" C++?
Or in other words: if you see a slowdown of 100x in debug mode, I would be really concerned about why the performance is so heavily dependent on the optimizer doing it's thing and would start investigating what's the reason for such a massive slowdown.
As far as I can tell, this is worse than for the average C++ codebase. I have some ideas for why the optimizer is able to achieve such large improvements with this particular code and some of that could surely be done with better source, but it's a huge code base and a refactoring on that scale just isn't going to happen.
Anyway the way I deal with it is to mark functions I want to debug with a macro that disables optimizations just for that function.
tracy_force_inline void swap( Vector& other )
{
uint8_t tmp[sizeof( Vector<T> )];
memcpy( (char*)tmp, &other, sizeof( Vector<T> ) );
memcpy( (char*)&other, this, sizeof( Vector<T> ) );
memcpy( (char*)this, tmp, sizeof( Vector<T> ) );
}
This is quite fast in debug.Will people who write C++ in 202x gamedev do it? Nah, I don't think so. Just stop even maintaining that pesky 'Debug' build and it will be fine. Build configurations grow in other direction. There are optimized configurations already that do not need local build step - LTO/PGO and friends. People just do not build that locally and real world performance is there.
YMMV of course.
If you've got a time traveling / reversible debugger than you can (sometimes) go back to a point where the value was being written / used, at which point it'll often reappear in scope and be accessible.
I believe DWARF's built-in virtual machine should be able to recompute missing values in many cases but I don't think compilers are great at putting the relevant info in, even where it should be possible to compute the right value fairly easily.
e.g. if the value you're interested in is being passed to / returned from a function then inspecting it around the call / return site should have the value available.
Pass various arguments to `backtrace` rather than just relying the default. Chances are it will have some non-optimized-out variables, which you can use to figure out what's going on.
Use `info registers` and see what looks like a pointer, then cast it to a type you suspect it is. Note that this can be done for any stack frame.
In that case, the code did become pretty hard to debug due to the extensive inlining and reordering it had allowed. Unfortunate because the only reason such functions exist is to make the structure of the code more apparent!
Maybe that's an exception (and / or maybe it's easier with C than for C++).
Maybe the less is that it's still always worth trying function call boundaries, in case the compiler has been conservative!