Move native capture leaf paths into walk results

Merged
VA
2d ago
+375-0

Native capture copied every non-directory path immediately before transferring it into a walk result. Move the original path into that result instead. Directory paths still retain separate owners for the output and pending recursion.

Lower bound: one owned path per leaf per walk; zero intermediate full-path clones. The old host and checkout walks each allocated a component vector and copied every component, then dropped the original. A leaf at depth d paid d+1 extra charged allocations per walk. The new branch preserves the admission check and transfers the original allocation custody into the result.

Paired production release measurements on bb1, identical base e9df7b8b0, default filesystem features, three alternating process pairs per case/subscriber, three measured rescans per process. Accounting remains enabled throughout; none means no tracing subscriber.

Fixture / subscriberHeap allocations before → afterAllocated bytes before → afterFirst paired median before → afterConfirmation median before → after
128 empty / none4,878 → 4,1101.626 → 1.592 MB14.05 → 13.24 ms11.09 → 10.85 ms
128 × 80 B / none14,498 → 13,73019.430 → 19.400 MB39.70 → 41.47 ms25.01 → 24.14 ms
128 empty / TRACE5,652 → 4,8841.641 → 1.607 MB14.86 → 18.41 ms11.18 → 10.92 ms
128 × 80 B / TRACE17,576 → 16,80819.490 → 19.460 MB41.69 → 47.45 ms24.67 → 25.63 ms

The repeat used the same binaries with the initial pair order reversed. Both runs reproduce exactly 768 fewer physical allocations per rescan (15.7% for empty files, 5.3% for dense files without tracing). Timing varies substantially across runs; TRACE dense medians regress, so this PR claims the allocation reduction only. Median live-heap peaks remain approximately 337–368 KB; RSS spans 7,724–10,352 KiB with no established reduction. The production delta is 11 lines plus cfg(test) hooks; no public API, parsing algorithm, synchronization or unsafe code changes.

Verification:

  • A shared real host tree and captured checkout back a 64-case shrinking differential property, plus a deterministic full-tree control. Both production walks must match the scalar filtered path set across root/nested subtrees, exclusions, path limits and repeated insertion. The fixture includes Unicode names, empty directories and hard-link aliases. Host observations retain identity and metadata; every transient scope returns live bytes to the fixture baseline on the original ledger.
  • The old-copy control invokes the original production path-cloning helper. Receipts must differ by exactly the component-vector/name allocations, path components and copied/read name bytes predicted from leaf depth. The physical heap oracle below is independent of those receipts and their differences. Directory copying stays unchanged.
  • Earlier production validation (989137dc3): Linux capture: 34 passed / 1.42 s. MSVC new property: 1 passed / 0.11 s; remaining capture regressions reused that binary: 31 passed / 3.34 s. Windows GNU filesystem --lib --tests --features distributed check passed (67.5 s compilation). Formatting, caller search and diff checks passed. Test compilation excluded from suite times: final Linux 5m14s, MSVC 8m45s. Release baseline / candidate: 144 / 63 s.
  • Separate strace probes preserve dense whole-process counts: statx 2,571; name_to_handle_at 2,048; openat 666; pread64 514; close 672; read 24; write 1,006 in both variants and subscriber modes. These include setup, initial capture and three rescans. Plain futex calls remain 2,561; TRACE 2,561 → 2,609. No syscall or contention improvement is claimed.
  • Steady receipt allocation operations: 13,187 → 12,675; source path components: 896 → 640; copied/read name bytes decrease by 1,536. Backend reads remain 1,927, bytes hashed 246,198, encoded bytes 66,704, object bytes written 20,352, logical peak 316,528. Remaining item counts vary with host identity ordering. No performed I/O or data-work charge is removed.

Review follow-up: production_leaf_walks_have_no_redundant_heap_copy wraps each actual host/checkout walk in acyclic_test_support::measure. A six-path tree includes root and nested leaves, Unicode and a hard-link alias. Setup, directory-proof cache warming and teardown stay outside the measurement; each measured scope returns live allocation custody to its fixture baseline. No tracing subscriber is installed, and accounting remains enabled.

Platform / production walkFixed exact heap requestsRestored-copy control
Linux / host5873
Linux / checkout211226
Windows MSVC / host5570
Windows MSVC / checkout211226

The literals accept both normal measurements. The restored-copy control must fail that same equality predicate; it adds 15 physical requests / 630 bytes in each walk. The assertion reads no work receipt and derives no bound from the control, so a redundant copy added to both variants, including an uncharged NamespacePath::clone(), fails it.

Reproduce the paired physical counts (one test prints candidate, restored-copy and repeated-candidate measurements):

Q:/lanes/bs.ps1 cargo test --locked -p acyclic-fs --lib native_capture::leaf_path_tests::production_leaf_walks_have_no_redundant_heap_copy '--' --nocapture
Q:/lanes/lb.ps1 cargo test --locked -p acyclic-fs --lib native_capture::leaf_path_tests::production_leaf_walks_have_no_redundant_heap_copy '--' --nocapture

Final focused qualification: Linux 2 passed / 0.11 s; Windows MSVC 2 passed / 0.11 s (build time excluded). Both execute these exact names:

test native_capture::leaf_path_tests::production_leaf_walks_have_no_redundant_heap_copy ... ok
test native_capture::leaf_path_tests::moved_leaves_match_copying_walks_and_eliminate_only_redundant_work ... ok

Final Windows GNU compile proof passed (72.54 s): Q:/lanes/bs.ps1 cargo check --locked -p acyclic-fs --lib --tests --features distributed --target x86_64-pc-windows-gnu. Final focused builds took Linux 6m32s and MSVC 9m08s; suite times above exclude compilation. Formatting and diff checks passed.
Reproduce the focused property:

Q:/lanes/bs.ps1 cargo test --locked -p acyclic-fs --lib native_capture::leaf_path_tests:: '--' --nocapture

Reproduce paired rescans from saved release binaries in the lane's CARGO_TARGET_DIR on bb1:

for trace in 0 1; do
  for sample in 0 1 2; do
    if [ $((sample % 2)) = 0 ]; then variants="before after"; else variants="after before"; fi
    for variant in $variants; do
      if [ "$trace" = 1 ]; then
        ACYCLIC_BENCH_TRACE=1 "$CARGO_TARGET_DIR/hf_leaf_$variant" --bench --timer os --color never --exact 'native_capture::rescan::(128, 80)'
      else
        env -u ACYCLIC_BENCH_TRACE "$CARGO_TARGET_DIR/hf_leaf_$variant" --bench --timer os --color never --exact 'native_capture::rescan::(128, 80)'
      fi
    done
  done
done

Saved test binaries for direct reruns: Windows target/hf_leaf_heap_windows_tests.exe native_capture::leaf_path_tests:: --nocapture; bb1 $CARGO_TARGET_DIR/hf_leaf_heap_linux_tests native_capture::leaf_path_tests:: --nocapture. These contain the final verification source and avoid rebuilding.

Signed head: 9a152d6b4abe97f025621d87a738442339e4dcaf. The production source is unchanged from the measured candidate; the follow-up adds only the physical allocation test. Earlier capture-suite results remain applicable, and final focused results are recorded above.

Decisions: retain the existing directory recursion and result types. Eliminate only work belonging to the discarded leaf copy; every performed allocation, host query and output insertion keeps its existing charge and bounds. Profiling and paired-run helpers stay outside the PR.