Skip to content

Add copy-on-write write-path counters#51

Open
MesTTo wants to merge 2 commits into
Adam-Vandervorst:masterfrom
MesTTo:pr/pathmap-cow-counters
Open

Add copy-on-write write-path counters#51
MesTTo wants to merge 2 commits into
Adam-Vandervorst:masterfrom
MesTTo:pr/pathmap-cow-counters

Conversation

@MesTTo

@MesTTo MesTTo commented Jul 4, 2026

Copy link
Copy Markdown

Summary

A follow-up to #46, which you correctly flagged as dead plumbing (the
record sites and readers had zero callers). This time the writer and reader
are both wired to real code:

  • Writer: two lines in TrieNodeODRc::make_unique — the one choke point
    every structural write in the library goes through — record whether the
    call found the node already unique or had to pay the copy-on-write clone.
    Compiled out entirely without the counters feature; the default build is
    byte-for-byte unchanged.
  • Reader: cow_counters() / reset_cow_counters() return a
    CowCounters { make_unique_calls, cow_clones } snapshot, exercised by an
    integration test in its own process: writing an unshared trie records zero
    clones, writing while another handle aliases it records at least one clone
    (and never more clones than calls), the aliased handle is unaffected, and
    writes after the alias is dropped stop cloning.

Also includes a standalone fix: the counters feature didn't compile on
master (an import of a zipper_priv::ZipperPriv that no longer exists —
get_focus moved to the public ZipperInfallibleSubtries — plus a doc
example referencing an undefined map and leaving a generic parameter
uninferred). Fixed as its own commit before adding the new counters.

Test plan

  • cargo test --release --features counters (660/0 lib, 9/0 doc)
  • cargo test --release --features counters --test cow_counters (1/1)
  • cargo test --release with the feature off (660/0, unchanged)

MesTTo added 2 commits July 5, 2026 04:43
The counters module rotted while the feature was off: it imports ZipperPriv,
which no longer exists (get_focus moved to ZipperInfallibleSubtries, already
in the zipper glob), and its doc example references an undefined map and
leaves print_traversal's free V parameter uninferred. With the import dropped
and the example given a real map and a turbofish, cargo build/test/doc all
pass with --features counters.
Extends the counters feature with the write-side split it was missing: every
structural write funnels through TrieNodeODRc::make_unique, which either finds
the node unshared or pays the copy-on-write clone. Two process-wide relaxed
atomics record that split (make_unique_calls / cow_clones), exposed as a
CowCounters snapshot with a reset, so a workload's write amplification under
aliasing is directly measurable.

The hook is two lines in make_unique, compiled out entirely without the
feature (the default build is unchanged). An integration test pins the
semantics in its own process: unshared writes record zero clones, writing an
aliased trie records at least one and never more clones than calls, the
aliased handle stays untouched, and dropping the alias stops the cloning.
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.

1 participant