jonhoo/inferno

Documentation, especially of folded format

kelko opened this issue · 3 comments

Maybe this is obvious for all the rest, but I have a very hard time to understand what string format exactly I should write as input into stdin of inferno-flamegraph.
I understand, that this library follows the original FlameGraph from brendangregg, but even when searching there I couldn't find a comprehensive and understandable definition of the input format. Most talks about what tools to use for which language (trace, dtrace, perf, ...) and how to collapse their outputs.

I'm comming from a different direction and want to re-format timing information I collect from within a program so that I can use flamegraph as visualization. So I don't need to understand how to combine perf & collapse & ... but I would like to know what format I need to write to be able to generate expressive flame graphs. As inferno-flamegraph is usable as standalone tool I would like to ask you whether you could extend your documentation also on those aspects.

I understand that basic form is:

action[;subaction]* (space) count

But some questions still arise:

  • Should the count be some of this and all sub-actions, or this without any samples/time spend in sub-actions?
  • If I want to generate the "flame chart" instead of "flame graph", what should I consider additionally, or is the input 1:1 the same (which seems weird, as --flamechart only reverses order)? In my test it seemed I did have to uniquely distinct the frames (I used timestamp). Not sure if this is correct
    • if I need such distinction key: can I somehow mark it as not being rendered but just used internally?
  • Can I add some information shown on hover but not as part of the stack names?

Additionally, but linked to this:
I see there are some CLI options like --nameattr or --nametype which seem to have effect on how the folded format content is drawn. Is there any documentation on those somewhere?

Hi there!

Ideally, this should all be documented on https://docs.rs/inferno/latest/inferno/flamegraph/fn.from_lines.html, but at the moment it is a little thin. There's also some documentation of the format in the original flamegraph.pl: https://github.com/brendangregg/FlameGraph/blob/cd9ee4c4449775a2f867acf31c84b7fe4b132ad5/flamegraph.pl#L18-L29

For your questions:

  • The count should be without samples spent in sub-actions
  • The input format for flamecharts are the same. The --flamechart argument just makes it so that stacks by the same name/prefix aren't merged, and instead the stacks are printed out in time-order (assumed to be input-order). At least that's the case based on my memory of the feature.
    • I don't think you're supposed to need a distinguisher when using --flamechart mode 🤔
  • No, there's not currently any way to add to the hover text.

The CLI options are documented here: https://docs.rs/inferno/latest/inferno/flamegraph/struct.Options.html, and that documentation should be replicated in the CLI when you run --help. They are defined here:

struct Opt {
.

If you want to take a stab at doing a PR to improve the documentation, that'd be great!

Hey @jonhoo . Thanks for the answer.

But I would like to come back to the flamechart feature, because after reading your answer I suspect there might be a bug:

You wrote "so that stacks by the same name/prefix aren't merged". I created a simple test input:

A 2
A;B 2
A;B 2
A 3
A;B 2
A;B 2

Based on your answer I would suspect the flamechart to have 2 "A" and 4 "B" elements. But the actually generated SVG has 1 "A" (merged both A) and 2 "B" (merged both consecutive "B", without the "A" line in between):

example_flamechart

This is the reason why I was unsure about whether or not some kind of unique identifier was necessary

Ah, yes, so, the effect of --flamechart is really to just not re-sort the input. The rest of the plotting code remains the same, which includes walking up and down adjacent stacks to merge them. That's why you're observing that it merges your adjacent A;B stacks. If you think about it, it sort of makes sense: it needs to merge the A's underlying those Bs, so some amount of merging has to happen. And following that argument, why should the Bs not be merged but the A's should? And similarly, why should the A on line 4 not be merged with the preceding As? Without knowing the semantics of your program, I think the best it can do is merge any frames that are immediately-horizontally-adjacent to a frame by the same name as itself (which is what the code currently does).