Skip to content

perf: fix slow /packets?groupByHash=true on large stores#2

Open
efiten wants to merge 3 commits intomasterfrom
fix/grouped-packets-perf
Open

perf: fix slow /packets?groupByHash=true on large stores#2
efiten wants to merge 3 commits intomasterfrom
fix/grouped-packets-perf

Conversation

@efiten
Copy link
Copy Markdown
Owner

@efiten efiten commented Mar 31, 2026

Summary

  • Adds LatestSeen field to StoreTx, maintained in all three observation write paths (load, real-time ingest, poll) — eliminates the O(n×observations) scan that was happening per packet at query time
  • Builds grouped packet maps under read lock (correct), sorts the local copy outside the lock — avoids holding the lock during O(n log n) sort
  • Caches the full sorted result for 3 seconds keyed by filter params — repeated requests within TTL return instantly without re-sorting

Fixes /packets?limit=50000&groupByHash=true taking 16s on large stores.

Test plan

  • Deploy to staging: ./deploy-staging.sh fix/grouped-packets-perf
  • Open packets page and confirm load time is well under 1s
  • Check [SLOW API] log in browser console is gone
  • Verify packet data is correct (hashes, counts, observer counts)

🤖 Generated with Claude Code

@efiten efiten force-pushed the fix/grouped-packets-perf branch from 38e1e38 to f80974b Compare March 31, 2026 14:19
efiten and others added 2 commits April 1, 2026 14:58
- Add LatestSeen field to StoreTx, maintained in all three observation
  write paths (load, real-time ingest, poll). Eliminates the per-packet
  observation scan that was O(total_packets * avg_observations).
- Build grouped packet maps under read lock (correct), sort the local
  copy outside the lock (avoids holding lock during O(n log n) sort).
- Cache the full sorted result for 3 seconds keyed by filter params.
  Repeated requests within the TTL return instantly without re-sorting.

Fixes /packets?limit=50000&groupByHash=true taking 16s on large stores.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
GetChannels was iterating all payload-type-5 packets and JSON-unmarshaling
each one while holding s.mu.RLock(), blocking all concurrent reads.
On stores with many channel messages this caused /api/channels to take 13s+.

- Copy only the needed fields under the read lock, release before unmarshal
- Cache the result for 15 seconds keyed by region param
- Invalidate cache on new packet ingestion

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@efiten efiten force-pushed the fix/grouped-packets-perf branch from f80974b to 3bf1df5 Compare April 1, 2026 13:01
…channel cache

- TestLatestSeenMaintained: verifies StoreTx.LatestSeen is set >= FirstSeen
  and >= all observation timestamps after store load
- TestQueryGroupedPacketsSortedByLatest: verifies packets with more-recent
  observations sort before packets with newer first_seen but older observations
- TestQueryGroupedPacketsCacheReturnsConsistentResult: verifies cache returns
  consistent total and ordering on back-to-back calls
- TestGetChannelsCacheReturnsConsistentResult: verifies GetChannels cache
  returns same channel names on repeated calls
- TestGetChannelsNotBlockedByLargeLock: verifies GetChannels returns correct
  data (channel name, messageCount) after lock-copy-unmarshal refactor

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@efiten efiten force-pushed the master branch 2 times, most recently from 41bf3b9 to f0fc940 Compare April 1, 2026 21:20
@efiten efiten force-pushed the master branch 2 times, most recently from 493d9e8 to 568de4b Compare May 1, 2026 22:16
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