Frame-pointer-based, I imagine?
Frame-pointer-based, I imagine?
The main two tricks are: it preprocesses all of the DWARF info at startup for faster lookups, and it dynamically patches the return addresses of functions on the stack injecting an address to its own trampoline, which allows it to skip going through the whole stack trace every time it needs to dump a backtrace. For example, if you're running a function nested 100 stack frames deep and that function calls malloc 100 times then Bytehound will only go through ~300 stack frames in total (~100 times for the first call then only ~2 frames for each successive call, if my math is right), while other similar tools will go through 10000 stack frames (going through all ~100 frames to the very bottom for every call).
Also nice use of Gimli - did something similar to make creating stack traces on crash cheaper to symbolicate.
For performance profiling I find that `perf`-like sampling profiling works well enough to find the hot spots, and then Valgrind's Callgrind is great for micro-optimizing the hot spots code on the assembly level.
Of course, it would be cool to have a unified memory + performance analysis tool like this, but I don't think I can justify the time investment to write one in my spare time.
Yeah, I'm really happy that Gimli exists, considering the absolute insanity/complexity pit of DWARF.
TP 5.0 from 1988 was the first version that had it.
The idea was to make sure the code the CPU returned to would actually be in memory.
I'm pretty sure Windows 1.0 did something very similar.
[1] https://github.com/koute/not-perf/blob/master/nwind/src/loca...
I'm curious if you've done any benchmarking for your implementation as well?
Nice!
> I'm curious if you've done any benchmarking for your implementation as well?
Not in any detail; I just checked that it's significantly faster than doing it naively and left it at that since it was fast enough for my use case.
However you then still need debug symbols of some kind to convert those to names.