Comment by shermantanktop
1 day ago
Flamegraphs are wonderful.
Me: looks at my code. "sure, ok, looks alright."
Me: looks at the resulting flamegraph. "what the hell is this?!?!?"
I've found all kinds of crazy stuff in codebases this way. Static initializers that aren't static, one-line logger calls that trigger expensive serialization, heavy string-parsing calls that don't memoize patterns, etc. Unfortunately some of those are my fault.
I also like icicle graphs for this. They're flamegraphs, but aggregated in the reverse order. (I.e. if you have calls A->B->C and D->E->C, then both calls to C are aggregated together, rather than being stacked on top of B and E respectively. It can make it easier to see what's wrong when you have a bunch of distinct codepaths that all invoke a common library where you're spending too much time.)
Regular flamegraphs are good too, icicle graphs are just another tool in the toolbox.
So someone else linked the original flamegraph site [0] and it describes icicle graphs as "inverting the y axis" but that's not only what's happening, right? You bucket top-down the stack opposed to bottom-up, correct?
[0] https://www.brendangregg.com/flamegraphs.html
It's certainly possible that what I encountered, labeled as an 'icicle graph', is a nonstandard usage of the term. But if so, that's a shame. I don't think inverting the y-axis is useful by itself, the different bucketing is what makes for an actually useful change.
Right, what is needed is something trie-like, with the root being the most fine-grained call.
Also cool that when you open it in a new tab, the svg [0] is interactive! You can zoom in by clicking on sections, and there's a button to reset the zoom level.
[0]: https://questdb.com/images/blog/2026-01-13/before.svg
Yes, they are made with: http://www.brendangregg.com/flamegraphs.html and
https://github.com/brendangregg/FlameGraph
Useful site if you are on to perf/eBPF/performance things with many examples and descriptions even for other uses as e.g. memory usage, disk usage (prefer heatmaps here but they are nice if you want to send someone a interactive view of their directory tree ...).
I always found profiling performance critical code and experimenting with optimisations to be one of the most enjoyable parts of development - probably because of the number of surprises that I encountered ("Why on Earth is that so slow?").
I might be very wrong in every way but, string parsing and or manipulating and memoiziation... sound like a super strange combo? For the first you know you're already doing expensive allocations, but the 2nd is also not a pattern I really see apart from in JS codebases. Could you provide more context on how this actually bit you in the behind? memoizing strings seems like a complicated and error prone "welp it feels better now" territory in my mind so I'm genuinely curious.
In Java it can be a bad toString() implementation hiding behind a + used for string assembly.
Or another great one: new instances of ObjectMapper created inside a method for a single call and then thrown away.
To be clear this is often sloppy code that shouldn’t have been written. But in a legacy codebase this stuff can easily happen.
> but the 2nd is also not a pattern I really see apart from in JS codebases.
If you're referring to "one-line logger calls that trigger expensive serialization", it's also common in java.
I've never used flamegraphs but would like to know about them. Can you explain more? Or where should I start?
Flame graphs have an official web site, maintained by Brendan Gregg, who invented them: https://www.brendangregg.com/flamegraphs.html. It's a useful starting point.
I use them all the time on Perl code.
https://metacpan.org/pod/Devel::NYTProf
I would also try hotspot, it is a interactive viewer for perf graphs.