Skip to content

perf: release dropped attribute storage after prehashing each queried rule - #615

Merged
tinder-maxwellelliott merged 1 commit into
Tinder:masterfrom
maxwellE:perf/shrink-prehashed-attributes
Nov 3, 2026
Merged

tinder-maxwellelliott merged 1 commit into
Tinder:masterfrom
maxwellE:perf/shrink-prehashed-attributes

Conversation

@maxwellE

@maxwellE maxwellE commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

Summary

prehash_rule hashes a rule's attributes as soon as its query batch is decoded and then keeps only tags and visibility with Vec::retain. retain drops the removed attributes' contents but keeps the vector's buffer. Attribute is 464 bytes and every queried rule carries dozens of them (all implicit attributes are in the proto), so each rule pinned tens of KB of dead capacity until hashing finished. On the large synthetic workspace that was about 420 MiB of the process's 665 MiB peak.

The fix calls shrink_to_fit() after the retain (which also covers the existing empty case). The existing prehash test now asserts capacity equals length.

Hash output, dependency edges and impacted sets are byte-identical on every workload.

Performance (make perf-proof)

Verdict: IMPROVED, no regressions. Linux, 2 vCPU / 7.8 GiB, Bazel 8.8.2, 5 interleaved iterations, --builder cargo (the --config=release build needs hosts this environment cannot reach). Base 6177715 (71.0.0), candidate tree 87ef848.

workload stage bazel-diff peak RSS bazel-diff CPU
small (2k rules) generate-hashes warm 103.3 → 93.1 MiB (-9.9%, p=0.008) unchanged
medium (7.5k rules) generate-hashes warm 291.3 → 175.1 MiB (-39.9%, p=0.008) 0.205 → 0.188s (-8.5%, p=0.008)
medium generate-hashes --depEdgesFile 289.3 → 173.2 MiB (-40.1%, p=0.008) 0.205 → 0.187s (-9.2%, p=0.016)
large (20k rules) generate-hashes cold 665.5 → 245.4 MiB (-63.1%, p=0.008) 0.554 → 0.441s (-20.5%, p=0.008)
large generate-hashes warm 663.4 → 247.3 MiB (-62.7%, p=0.008) 0.502 → 0.433s (-13.6%, p=0.008)
large generate-hashes --depEdgesFile 667.3 → 239.2 MiB (-64.1%, p=0.008) 0.551 → 0.432s (-21.6%, p=0.008)

get-impacted-targets is unchanged (it does not query). The CPU gain is mostly system time (page faults on the retained buffers). The full harness report is perf-proof-summary.md.

Testing

  • cargo test --release --lib: 253 passed
  • make perf-proof: correctness table identical on small, medium and large

Claude for Maxwell

… rule

prehash_rule kept only tags and visibility via Vec::retain, which leaves the
decoded buffer allocated. Attribute is 464 bytes and a queried rule carries
dozens of attributes, so every rule pinned tens of KB of dead capacity until
hashing finished. shrink_to_fit after the retain returns it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KJs3XytsGbjrXc37W1GZP5

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

No active review issues remain for the prehashing attribute-capacity cleanup.

No open issues 🎉

What changed in this PR

This PR reduces memory retained during rule prehashing by releasing unused attribute-vector capacity after keeping only tags and visibility, without changing hash computation.

Changes:

  • Replace empty-vector cleanup with shrink_to_fit() to reclaim unused capacity for all prehashed rules.
  • Extend the existing prehash test to assert that attribute capacity equals length.
File Description
src/​hash.rs Reclaims unused attribute storage after prehashing and adds a capacity assertion to the existing test.

Review effort: Balanced

@tinder-maxwellelliott
tinder-maxwellelliott merged commit 159ba6b into Tinder:master Nov 3, 2026
19 checks passed
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.

3 participants