p2p: cache per-message ingress gauges to avoid allocs in Peer.handle#21920
Merged
Conversation
JkLondon
approved these changes
Jun 22, 2026
d7c47d6 to
b4ffab2
Compare
Contributor
There was a problem hiding this comment.
Pull request overview
This PR aims to reduce per-inbound-message overhead in Peer.handle when metrics are enabled by caching ingress byte/packet gauges on protoRW and updating them via a helper (meterIngress) rather than performing per-message metric lookup/registration work.
Changes:
- Replace direct per-message gauge updates in
Peer.handlewith aprotoRW.meterIngresshelper. - Add
protoRW.meterIngressto lazily allocate/cache per-message-code ingress gauges. - Add tests verifying gauge values and asserting zero allocations after cache warm-up.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
p2p/peer.go |
Routes ingress metering through protoRW.meterIngress and adds the caching/lazy-init helper. |
p2p/peer_test.go |
Adds correctness + allocation regression tests for meterIngress. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Peer.handleruns in the per-peer read loop for every inbound subprotocol message. With metrics enabled it did, per message:That allocated, per message: the
Sprintfstring, the+ "_packets"string, two&gauge{}wrappers fromGetOrCreateGauge, and the variadic arg boxing — and eachGetOrCreateGaugealso took a mutex + map lookup. The gauge identity only depends on(proto.Name, proto.Version, relativeCode), all stable for the lifetime of aprotoRW.Change
Cache the gauges per
protoRW, indexed by the protocol-relative message code. The first message for a code creates and caches the gauges (preserving the original lazy registration — no zero-valued metrics for codes that never arrive); subsequent messages just index the slice and callSet.Behavior is identical: same gauge names, same values. Safe without locking because
handleonly runs in the single per-peer read-loop goroutine and each peer owns its ownprotoRWinstances (confirmed under-race).Numbers
Benchmarked on the actual code path (
benchmem, Apple M4 Max):5 allocations → 0 per inbound message, ~46× faster per call.
Tests
TestProtoRWMeterIngress— verifies the byte/packet gauges still receive the correct values.TestProtoRWMeterIngressNoAllocs— asserts0 allocs/opafter warmup (regression guard).