Pool memqueue producer response channels via sync.Pool#49337
Pool memqueue producer response channels via sync.Pool#49337
Conversation
|
This pull request doesn't have a |
|
This pull request does not have a backport label.
To fixup this pull request, you need to add the backport labels for the needed
|
Use sync.Pool to reuse chan queue.EntryID response channels in both forgetfulProducer and ackProducer instead of allocating a new channel per publish request. Channels are obtained from the pool in makePushRequest and returned via defer in openState.publish and openState.tryPublish, with a drain step to handle any stale buffered response. Benchmark improvement (BenchmarkProducerThroughput): - Allocs/op: ~10,007 → ~4-5 (99.95% reduction) - Memory/op: ~1,120,530 B → ~187-322 B (99.97% reduction) Co-authored-by: strawgate <6384545+strawgate@users.noreply.github.com>
Co-authored-by: strawgate <6384545+strawgate@users.noreply.github.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughAdds a global 🚥 Pre-merge checks | ✅ 2✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
Comment |
Handle sync.Pool type assertion with an ok-check and fallback channel allocation to satisfy golangci-lint errcheck without changing behavior. Made-with: Cursor
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@libbeat/publisher/queue/memqueue/produce.go`:
- Around line 151-152: The publish function currently defers
putRespChan(req.resp) immediately, which can return the response channel to the
pool while the queue goroutine may still send to it (race between st.events <-
req and handlePendingResponse), causing a pooled channel to receive a stale
EntryID; remove the early defer in openState.publish and instead call
putRespChan(req.resp) only on the error/early-return paths where the request is
not enqueued (i.e., when you know the queue goroutine will not send), and let
the consumer of the request (the queue goroutine/handler) be responsible for
returning req.resp to the pool after it has sent or closed the response; update
paths that call handlePendingResponse and any return branches to avoid returning
the channel to the pool when st.events <- req succeeded.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 8403320f-eba1-45f2-99e6-674c31af592e
📒 Files selected for processing (1)
libbeat/publisher/queue/memqueue/produce.go
Only return response channels to the pool when publish ownership is unambiguous; avoid recycling on ambiguous queue-closing paths to prevent stale sends into reused channels. Made-with: Cursor
forgetfulProducer.makePushRequestandackProducer.makePushRequestallocate achan queue.EntryIDper publish call. On theBenchmarkProducerThroughputpath this dominated the allocation profile (~96% of alloc_space).Pool and reuse response channels with
sync.Pool, matching the existingbatchPoolpattern inbroker.go.respChanPool(sync.Pool) producingmake(chan queue.EntryID, 1)getRespChan()/putRespChan()acquire and release;putRespChandrains any stale buffered value before returning to poolmakePushRequestvariants now callgetRespChan()instead ofmakeopenState.publishandopenState.tryPublishreturn the channel viadefer putRespChan(req.resp)Original prompt
💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.