Repository navigation
perf(store): key byNode's de-dup sets by transmission ID - #2199
Conversation
Red: nodeHashes keeps 25.8MB for 500k (node, packet) pairs, keyed by the packets' hash strings. newNodeSets and nodeHasTx wrap today's map. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KaR4xu8gVykQBkH8yG8m6H
nodeHashes is the set behind byNode's de-dup: for every node, the transmissions already listed under it. It was keyed by each transmission's 16-character hash string: ~650k entries and 21.5MB on a busy week. It is now keyed by transmission ID, the same membership (a store holds one transmission per hash); eviction deletes by ID, and the health region filter matches regional observations by transmission ID. nodeHasTx reads the set for callers and tests. On a copy of that week: the sets' live heap 21.5MB -> 13.2MB. Fixture (500k pairs): 25.8MB -> 18.0MB. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KaR4xu8gVykQBkH8yG8m6H
efiten
left a comment
There was a problem hiding this comment.
One test before merge; the change itself is right.
What I checked
- Keying.
- Hash and ID map one to one:
transmissionshasid INTEGER PRIMARY KEY AUTOINCREMENTandhash TEXT NOT NULL UNIQUE, and AUTOINCREMENT never reuses an ID. - Every write (
addToByNode) and both eviction loops switched keys together, so no set mixes hash and ID keys. - Every
addToByNodecaller passes aStoreTxbuilt from a DB row, sotx.IDis set. A duplicate object for a hash that is already loaded carries the same ID.
- Hash and ID map one to one:
- Unchanged: locking stays the same, and eviction still drops empty sets.
- Heap, same fixture as yours (500k pairs, 5 runs each): 26.12-26.15 MB on base, 18.30-18.34 MB on head. This matches your 25.8 to 18.0 MB. Your
TestNodeSetRetainedHeapis red on base (26.1 MB) and green on head. - Throwaway benchmark (500k adds plus 500k repeat adds,
-benchmem -count=6): B/op 63.83 MB to 47.70 MB, allocation count unchanged, time within noise. - Suite and interaction with other PRs:
go vetis clean.go test ./cmd/serverpasses on the head merged into current master.-raceon the ByNode/Evict/BulkHealth/Chunk tests passes.- None of the perf(store) PRs merged since your base touches
nodeHashes.
Requested change
-
The rewritten region branch of
GetBulkHealth(store.go:9806-9826) has no assertion. The two tests that reach it check nothing about the result:coverage_test.go:2232does_ = results;coverage_test.go:2662checks only the HTTP status.
If
regionalTxIDswere keyed by the wrong ID (an observation ID instead of the transmission ID, say), the suite would still pass. Please add a test that asserts which pubkeys come back for a region whose observer saw some nodes' transmissions and not others'.
Notes, not blocking
nodeHashes(store.go:200) and the eviction localshashesnow hold transmission IDs. The comment on the field is right, the names are not. Renaming tonodeTxIDswould fix that, or leave it to avoid churn.nodeHasTx(store.go:1922-1926) is only used by tests.- The comments at
store.go:1917-1919and in the header ofnode_set_memory_test.gocarry measured numbers ("~650k entries", "about 30% less", "21.5MB"). Those will go stale; the PR description is a better home for them.
…ard there Observation IDs differ from transmission IDs in the fixture, so a filter keyed by the wrong ID returns nothing and fails. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KaR4xu8gVykQBkH8yG8m6H
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KaR4xu8gVykQBkH8yG8m6H
|
Review feedback addressed (commits
🤖 Generated with Claude Code |
|
Bump |
efiten
left a comment
There was a problem hiding this comment.
Thanks, the region test is what I asked for. Approving.
What I checked at 41f6912b
TestGetBulkHealthRegionKeepsNodesHeardTherefails whenregionalTxIDs[o.TransmissionID](store.go:9813) becomeso.ID: both regions come back empty. It also fails with the region filter bypassed (both regions return a, b and c) and with relay indexing dropped inindexResolvedPathHops(EDI loses c), so the relay path is covered too.- Every non-test use of the sets keys by transmission ID:
addToByNode, both eviction paths, and theGetBulkHealthregion filter. All fouraddToByNodecallers pass a*StoreTx. go vetis clean,go test -count=1 ./...incmd/serverpasses, and-raceon the ByNode, Evict, BulkHealth and NodeSet tests passes. The branch merges cleanly with current master, and the merged tree passesgo testtoo.- Keeping the
nodeHashesname and the test-onlynodeHasTxis fine with me, for the reasons you gave.
Small points, not blocking
eviction_test.go:313printstx.Hashin its failure message, but the set holds transmission IDs now;tx.IDwith%dwould match.- The description's Tests section does not list the new region test yet.
I did not re-run the heap benchmark: the changes since fcc74512 are a test and comments.
Problem
nodeHashesis the set behindbyNode's de-dup: for every node, the transmissions already listed under it. It was keyed by each transmission's 16-character hash string. On a week of a busy network that's about 650k entries and 21.5 MB, four times the size ofbyNodeitself.Change
newNodeSetsandnodeHasTxwrap the map for callers and tests.Measured
Tests
TestNodeSetRetainedHeap: red commit first.TestAddToByNodeDedup.go test ./cmd/serverpasses.No config or UI changes.
🤖 Generated with Claude Code
https://claude.ai/code/session_01KaR4xu8gVykQBkH8yG8m6H