Skip to content

Add 'stacks' subcommand for folded/flame-graph output (#289) - #378

Open
ChrisJr404 wants to merge 1 commit into
Byron:mainfrom
ChrisJr404:feature/stacks-folded-output
Open

Add 'stacks' subcommand for folded/flame-graph output (#289)#378
ChrisJr404 wants to merge 1 commit into
Byron:mainfrom
ChrisJr404:feature/stacks-folded-output

Conversation

@ChrisJr404

Copy link
Copy Markdown

Adds a stacks subcommand that prints the whole traversal as folded stacks, so a dua run can be turned into a disk-usage flame graph without leaving the tool. This implements the request in #289.

The folded (a.k.a. "collapsed") format is what flame-graph tools like inferno and Brendan Gregg's flamegraph.pl read on stdin: one line per entry, its path with ; between components, a space, and its size in bytes. That makes the usual pipe work:

dua stacks | inferno-flamegraph > disk-usage.svg

A couple of design notes:

  • Rather than only emitting files (as Gregg's files.pl does), every entry gets a line carrying its own size: a directory contributes just the size of its directory entry, because the bytes it contains already show up on the lines of the things inside it. That avoids double-counting when the flame-graph tool sums a stack against its parents, and it means the folded lines sum to exactly the same total the other commands report — I added a test that checks this against a fresh traversal. Zero-sized entries are left out since they add nothing to a graph.
  • It reuses the existing traversal, so all the traversal options carry over (--apparent-size, --ignore-from, --count-hard-links, threads, and so on). Hard links are counted once by default, as elsewhere.
  • Entry names have the ; frame separator and any control characters replaced with _ so a single odd filename can't corrupt the line-based format.

I went with a subcommand rather than a flag on aggregate because the folded output needs the full in-memory tree, which aggregate doesn't build — but I'm happy to reshape the surface (name, flag vs. subcommand) if you'd prefer something else.

Example output:

$ dua stacks -A some_dir
a 80
a;big 5000
a;b 60
a;b;small 100
top 3

Testing: added four unit tests in src/stacks.rs covering the nested-file layout, the sum-equals-total invariant, a single-file input, and ;-in-name sanitization. cargo test is green (77 tests), cargo +nightly fmt --check is clean, and cargo +nightly clippy produces no new warnings from this change. Also smoke-tested by hand that dua stacks -A and dua aggregate -A --format bytes report the same total, and that the output pipes cleanly.

This lets non-interactive runs export the whole traversal in the folded
'collapsed' format read by flame-graph tools like inferno and Brendan
Gregg's flamegraph.pl, so a disk-usage exploration can become a single
shareable SVG via 'dua stacks | inferno-flamegraph > usage.svg'.

Each line is an entry's path with ';' between components followed by its
own size in bytes; a directory contributes only the size of its own entry
since its contents are printed on their own lines, so the lines sum to the
same total the other commands report. Traversal options (apparent size,
ignore patterns, hard-link counting, ...) are honored as usual.
@Byron

Byron commented Aug 18, 2026

Copy link
Copy Markdown
Owner

Can you please upload the SVG to this PR? I want to take a look. Please beware of PII. Thanks so much.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants