oans v1.4.0
oans 1.4.0 is a large feature release focused on the dedupe phase, a
unified live progress UI, and honest observability — all backward
compatible with 1.3.0 (same CLI superset, same hashfile schema, hashfiles
carry over).
Highlights
- Fast dedupe on trees larger than RAM (~13× vs duperemove 0.15.2). When the
working set doesn't fit in the page cache, the kernel'sFIDEDUPERANGEbyte
compare re-reads cold. oans now keeps just-hashed data warm and prefetches each
dedupe round as fast sequential I/O (#107). Median hash+dedupe on a
cache-capped ~10.5 GiB tree: 13.8 s vs 179.7 s, at ~2× lower RSS and a
~1.8× smaller hashfile — byte-for-byte identical sharing. See
docs/benchmarks.md. - Streaming dedupe pipeline. The dedupe phase runs one persistent worker pool
with a bounded double-buffered producer, so peak RSS stays low and flat
regardless of how many duplicate groups are in flight (#111, #112, #116). - Unified live progress UI across scanning / hashing / dedupe / done, with a
byte-weighted smooth dedupe bar and a weighted-progress scan ETA.
Dedupe
- Byte-weighted, smooth dedupe progress bar — moves 0→100% by kernel byte-verify
volume, even through one giant group (#111). - Order-independent extent loader; whole-file dup members excluded via a
correlated probe (#112). - Streaming pipeline with a persistent pool and generation-ordered watermark,
preserving the Ctrl+C safety invariant (#116). - Keep hashed data in the page cache for the dedupe phase and prefetch each
FIDEDUPERANGEround (#107).
Scan & progress
- Weighted-progress scan ETA (#98); retuned HDD per-file weight (#101);
"mapping:" phase shown during pre-read setup (#99). - Hash largest files first (LPT scheduling) to shrink the idle tail (#91).
- Skip all-hole blocks in sparse files (#87, #89).
- Refuse unsupported-fs roots up front instead of failing silently (#97); XFS
identified without root, with a loud failure when it can't (#85). - Warn instead of silently skipping paths over
PATH_MAX(#115). - Grow hash arrays geometrically (#95); block-aligned block-count estimates (#94).
- Scan diagnostics: contention/starvation counters, honest small-file ETA, no
more idle-flicker (#93).
Observability & reporting
--progress=json: machine-readable per-phase progress for dashboards.--statsrelabels "reclaimable" as "duplicated" (a logical figure, not a
to-do) (#84).- Self-contained
--help/usage instead of shelling out toman(#86).
Reliability & CI
- Fix a use-after-free and leak when recreating a rejected hashfile (#105).
- CI runs the unit + integration suites under valgrind, on btrfs and XFS (#106).