English · Русский · Deutsch · Français · Español · MIT License
A WinDirStat-style disk usage analyzer: shows what is eating your disk space as a treemap. Native Windows application in C (Win32 + Direct2D), no dependencies.
The main difference from WinDirStat is that the map is built while the scan is still running: large top-level folders show up immediately and keep splitting into subfolders as data arrives. You never wait for the walk to finish before seeing anything.
Full C: drive — 3,811,564 files, 386 GB, 14 seconds.
Download WinDirStat2026.exe from the releases page and run
it. No installation, no dependencies, about 550 KB.
Windows SmartScreen may warn about an unknown publisher — the binary is not signed with a certificate. Click "More info" → "Run anyway".
Requires Visual Studio Build Tools with the C++ workload and the Windows SDK.
build.bat
The path to vcvars64.bat is set at the top of build.bat — adjust it if your
installation is not under Program Files (x86)\Microsoft Visual Studio\2019\BuildTools.
Output: build\WinDirStat2026.exe (statically linked with /MT, so no Visual
C++ Redistributable is needed).
WinDirStat2026.exe start screen with drive picker
WinDirStat2026.exe C:\ scan immediately, skip the picker
WinDirStat2026.exe "C:\Program Files"
Without arguments the app first shows a list of drives — volume label, file system, used space and a fill bar (amber past 75%, red past 90%). The same screen offers "Choose folder…" for an arbitrary directory and an administrator privileges toggle.
Some system folders cannot be read without elevation, and their contents are left out of the totals — the status bar then says that some folders were inaccessible. The start screen has a "Run as administrator" entry that relaunches the app through UAC, after which the whole drive is readable.
A normal launch never triggers a UAC prompt (asInvoker) — elevation happens
only on explicit request.
| Left click | object menu: open, reveal in Explorer, copy path, properties |
| Double left click | enter folder |
| Right click / middle click / Backspace | go up one level |
| O | choose another folder |
| F5 | rescan |
| Esc | stop the scan, then return to the drive picker |
Tile color follows the file extension: identical types share a color. Steel-blue tiles are folders — they act as the backdrop under their contents.
The right-hand panel is more than a legend: every type has a checkbox. Uncheck
one and files of that type disappear from the map, with areas recomputed over
what remains — no gaps are left behind. The folder structure is preserved:
leave only .jpg checked and you see the entire directory hierarchy holding
nothing but images. Filters apply immediately on click.
"Select all" and "Clear all" toggle the whole list at once.
A separate logs row below the list matches every file whose name or
extension contains log, case-insensitively: app.log, Install.LOG,
debug_log_2024.txt, CBS.log. It works on top of the other checkboxes, which
makes it easy to hunt down bloated log files without guessing extensions.
In a short window the list is truncated with an "…N more" counter; in a narrow one the panel is hidden entirely.
Measured on an NVMe SSD, NTFS, 8 cores:
| Target | Files | Time |
|---|---|---|
C:\Program Files |
171,239 | 0.4 s |
Full C: drive |
3,811,564 | 14 s (386 GB, ~500 MB RAM) |
For comparison on the same C:\Program Files: a single-threaded C walk takes
4.5 s, a Node.js implementation 9.9 s. The first scan of a cold disk is slower —
on a warm filesystem cache the difference reaches 3–4x.
Where the speed comes from:
- Multithreaded walk. A thread pool drains a shared queue of directories. The pool is sized at twice the core count: directory enumeration is bound by disk latency rather than CPU, so while some threads wait, others work.
FindFirstFileExwithFindExInfoBasic— skips 8.3 short-name lookup, plusFIND_FIRST_EX_LARGE_FETCHto read in large batches.- Arena allocation instead of per-node
malloc. Nodes come from 1 MB blocks and are freed all at once — an order of magnitude cheaper across millions of files. - Sizes propagate to the root atomically, so every folder knows its subtree size at any moment and the map can be drawn without waiting for the walk.
- Sub-pixel branches are cut. Once a rectangle is thinner than a pixel the layout stops descending — there is nothing to draw, and the subtree below may be enormous. This is why layout cost scales with window size, not with the number of files on disk.
src/scanner.c multithreaded walk, node tree, arena, per-extension stats
src/treemap.c squarified layout (Bruls-Huizing-van Wijk)
src/main.cpp window, Direct2D, animation, legend, interaction
src/app.manifest DPI awareness, UTF-8, common control styles
main.cpp is the only C++ file, and only because d2d1.h/dwrite.h do not
compile as plain C. The code inside stays procedural — no classes, no STL.
The tree is read from the UI thread while the scanner is still filling it. That is safe because nodes never move or get freed once published, children are pushed onto the head of a list with CAS, and sizes change atomically: a reader may observe a slightly stale size, but never a dangling pointer.
- Windows only (Win32 API, Direct2D).
- Reports logical file size, not size on disk — no adjustment for cluster slack, NTFS compression or sparse files.
- Hard links are counted once per link, so their size is double-counted.
- Junctions and symlinks are not followed, to avoid walking in circles.
- Reading the MFT directly is not used: it always requires administrator privileges, while the regular walk works without them.
MIT — see LICENSE.
- Email: geo-ded@yandex.ru
- Telegram: @Jorg_Geo_Ded
The same links are in the app itself, in the right-hand panel.
Open to collaboration. Bug reports, ideas and pull requests are welcome via issues — in English, German, French or Spanish.
