# btdu: a sampling disk usage profiler for btrfs

> btdu is a GPL 2 licensed sampling disk usage profiler for btrfs, which estimates space use by taking random samples of the disk and looking up what is at each point, so it stays correct in the presence of compression, extent cloning and snapshots that make classic analyzers lie. The judgement is that the sampling approach is a deliberate trade, and that the emergent snapshot sizing is the feature no other tool offers.

**CyberShadow/btdu** — sampling disk usage profiler for btrfs

- Repository: https://github.com/CyberShadow/btdu
- Stars: 687 · Forks: 10
- Language: D
- License: GPL-2.0
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/cybershadow-btdu

## Why btrfs breaks the usual disk usage tool

btdu is a sampling disk usage profiler for btrfs, and the reason it exists is in the first paragraph of the readme.

Three btrfs features make it difficult to estimate what disk space is in use. Subvolumes allow cheap copy-on-write snapshots of entire filesystem trees, with unmodified data shared among the snapshots. File and extent cloning allow cheap copies of files or parts of them, with the extents stored only once. And compression transparently reduces disk usage further.

For those reasons, classic disk usage analyzers such as ncdu cannot provide an accurate depiction of actual disk usage. The readme is specific about the hard case, that btrfs compression in particular is challenging for the classic analyzers, and that special tools such as compsize have to be used to query compressed usage.

That is the problem in one sentence. A classic analyzer walks the tree and adds up the sizes of the files it finds, and on btrfs that sum is not what the disk is holding. The same file, present in five snapshots, occupies one copy, and a compressed file occupies less than its length. Any tool that adds up apparent sizes is answering a different question from the one an administrator asks when a volume is full.

So btdu takes a completely different approach. It queries the raw filesystem metadata rather than the file tree, which is why the readme says it requires root privileges to run.

The project is GPL 2 licensed, written in D, the last push was on 2026-09-27, and the release history is the 0.7 line with 0.7.0 on 2026-01-01, 0.7.1 on 2026-01-02 and 0.7.2 on 2026-01-05.

## The algorithm is four steps and a random point

The algorithm is described in four numbered steps, and it is worth reading them slowly because nothing about it walks the filesystem.

The first step is to pick a random point on the disk in use. The second is to find what is located at that point. The third is to add the path to the results. And the fourth is to repeat the above steps indefinitely.

So the tool never enumerates anything. It samples the address space of the disk, asks the filesystem what occupies each sampled address, and records the path. The tree of results is then a visualisation of a random sample of the disk, weighted by how much space each sample lands in.

The readme is honest about the consequence in one quoted phrase. Though it works by taking random samples, it is eventually accurate.

That word is doing the work. The estimate converges as the sample count grows, and the tool shows its results while it converges rather than after it, which is the property that makes the tool usable at all on a filesystem with tens of millions of extents.

The four differences from the classic analyzers follow directly from the algorithm. Results appear instantly, though wildly inaccurate at first, and they become progressively more accurate the longer it runs. The tool analyses entire filesystems only, with no way to analyse a particular subdirectory or subvolume. Extents used by multiple files are counted only once, and the shortest path is used when placing the sample in the tree for visualisation. And by nature of the algorithm it works correctly with compression and the other btrfs features.

## The emergent snapshot sizing is the real prize

The use cases are where the algorithm stops being a curiosity and starts being a tool, and the second one is the remarkable one.

The first use case is the obvious one, quickly summarising space usage. The readme notes that btdu needs only 100 samples to achieve roughly one percent resolution, which means it can identify space hogs very quickly, and that this is useful if the disk is full and some space has to be freed urgently to restore normal operation. That is a real operational difference from an analyzer that walks the whole tree first.

The second use case is estimating snapshot size, and the mechanism is a consequence of a design decision rather than a feature that was implemented. When an extent is in use by multiple files or snapshots, btdu has to decide where to place it in the browsable tree, and it picks the path with the shortest length, or the lexicographically smaller path if the lengths are equal. The readme then describes the emergent effect, that if your snapshots use a fixed-length lexicographically-ordered naming scheme, such as a date and time format, the size of a snapshot as displayed in btdu will indicate the data that occurs in that snapshot or any later one, that is, the amount of new data in that snapshot.

So the shortest path rule turns into a snapshot sizing tool without anyone writing a snapshot sizer. The naming scheme has to be sorted and fixed length, and then the number on the screen is the size of what that snapshot added.

The other three use cases are about the things a classic analyzer cannot see at all. You can estimate how much real disk space the compressed data occupies. You can estimate the space used by unreachable parts of extents, the data in extents that hold older versions of file content which has since been overwritten, which the readme calls the btrfs dark matter and which can be an easily overlooked space hog that goes away if you rewrite or defragment the affected files. And in the expert mode you get explanations for the hierarchy objects and the common errors, additional size metrics, and the logical and physical sampling modes that make sense of a RAID array with several profiles.

## Running it takes root and the top level subvolume

The usage section is short, and two of its instructions are the kind you only learn by getting them wrong.

The tool runs with root privileges, and the path you give it has to be the top-level subvolume. The readme explains why, otherwise btdu is unable to open the other subvolumes for inode resolution, and it suggests a way out if you are not sure, mounting the filesystem to a new mount point with the subvol and subvolid options set to the root.

```
# btdu /path/to/filesystem/root
```

That is the crux of the tool. To place a sample in the tree it has to resolve the inode of whatever it found, and the inode of a file in another subvolume is only resolvable if that subvolume can be opened, which means the path has to be the root of the filesystem rather than some directory inside it.

It also explains the design consequence, that btdu analyses entire filesystems only, with no way to analyse a particular subdirectory or subvolume. That is not a missing feature, it is the direct consequence of the sampling model, since a sample can land anywhere on the disk and the tool has to be able to name every file it might hit.

The rest is the usual. btdu --help prints the usage information, and the readme links the concepts document for the size metrics and the logical versus physical discussion if you want the detail behind the expert mode.

## Interactive by default, headless when you need a number

By default btdu launches a terminal user interface where you can browse the results interactively, and the behaviour of that interface is worth knowing about.

The key detail is that btdu keeps collecting samples to improve the accuracy until it is stopped, either by quitting or by pausing, which is done by pressing the p key. So the interface stays alive and still working after the numbers have stopped changing visibly, and a pause is what freezes the display rather than a quit.

The alternative is the headless mode. With the --headless switch, btdu runs without the interactive interface and prints a tree of the largest items to standard output, and the readme shows what that looks like with a maximum time of thirty seconds:

```
# btdu --headless --max-time=30s /mnt/btrfs
/mnt/btrfs (~97.56 GiB)
├── @home (~45.23 GiB)
│   ├── user (~30.12 GiB)
│   └── .cache (~12.34 GiB)
└── @root (~35.78 GiB)
```

That is the shape of the tool for scripting, where the answer you want is a summary rather than a browser, and the time limit gives the sampler a stopping point so the result is reproducible rather than the best number it happened to reach.

The tracking use case fits here too. The --compare switch compares the current disk usage against a previously exported baseline, showing what has grown or what has shrunk, and the readme is clear about why that is more useful than a snapshot of the totals, because it identifies the active space consumers, the files or directories that are accumulating data, rather than the ones that are simply large. It is the tool to reach for when a cache is quietly growing or when a cleanup needs to be verified rather than assumed.

## Building it with Nix, or with Dub and a D compiler

There are four ways to get btdu, and the readme presents them in decreasing order of convenience.

A distribution package comes first, if your distribution packages it, with a Repology badge for the status. Then a static binary from the releases page or from the latest continuous integration run. Then Nix, either running it directly with nix run pointed at the GitHub repository, or installing it permanently with nix profile install. And finally, cloning the repository and building from source.

The Nix path is the one the readme pushes, because of what the manual path requires. With Nix and flakes enabled you build with nix build pointed at the repository or locally, and the binary appears in the result directory. For development, nix develop gives you a shell with all the dependencies, and the build inside it is a dub build.

The manual path needs a D compiler, Dub if it did not come with it, and the wide character ncurses development package, and then the build is a single dub build with the release flag. The readme warns that not all software distributions package a compatible version of all the necessary dependencies, that success is not guaranteed, and that you should use the Nix build method if you run into issues. That is an unusual amount of honesty about build portability.

The repository explains the structure. There is a source directory, a continuous integration directory, the Dub package definition with its selections and lock file, the Nix flake, a man page, and two documents that matter for understanding the tool, CONCEPTS.md for the size metrics and the logical versus physical discussion, and ARCHITECTURE.md for how the program is put together.

## Conclusion

btdu fits a Linux administrator whose btrfs volume is full and whose usual analyzer is giving a wrong answer, because btdu counts the physical extents the filesystem actually allocates rather than the apparent size of the files, and because it needs a hundred samples to reach roughly one percent resolution, so it answers the urgent question fast. It is the wrong choice if you need an exact figure, since the numbers are estimates that improve as the run continues, and it is the wrong choice if you need to analyse one directory, because the tool deliberately works on whole filesystems only. Before you run it, point it at the top level subvolume, because otherwise it cannot resolve inodes in the other subvolumes, and be prepared for the interactive interface to keep working after the numbers stop changing, since it keeps sampling to improve them.

## FAQ

### What is btdu?

It is a sampling disk usage profiler for btrfs, written in D and licensed under the GPL. It estimates disk usage by repeatedly picking a random point on the disk, finding what occupies it and recording the path, so it stays correct with compression, extent cloning and snapshots, which defeat classic analyzers such as ncdu.

### Why does btdu need root and the top level subvolume?

It queries raw filesystem metadata, so it needs root privileges, and the path must be the top-level subvolume, otherwise it cannot open the other subvolumes for inode resolution. The readme suggests mounting the filesystem to a new mount point with the subvol and subvolid options if you are unsure.

### How accurate is btdu?

The results are an estimate that improves as it samples. Around 100 samples give roughly one percent resolution, which is enough to identify the largest space consumers quickly, and the tool keeps collecting samples in the interactive interface until it is quit or paused.

### How do I install btdu?

Through your distribution's package if it is packaged, from a static binary on the releases page, with Nix using nix run or nix profile install pointed at the GitHub repository, or by building from source. The readme recommends the Nix method because the manual build needs a D compiler, Dub and the wide character ncurses development package, and not every distribution ships compatible versions.

## Sources

- [CyberShadow/btdu on GitHub](https://github.com/CyberShadow/btdu)
- [Issues](https://github.com/CyberShadow/btdu/issues)
- [License: GPL-2.0](https://github.com/CyberShadow/btdu/blob/master/LICENSE)
- [README](https://github.com/CyberShadow/btdu/blob/master/README.md)
- [Releases](https://github.com/CyberShadow/btdu/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/cybershadow-btdu
