Use zero-copy ZMQ response relay - #1803
Merged
Merged
Conversation
Contributor
ApprovabilityVerdict: Approved This is a straightforward ZMQ performance optimization adding zero-copy ( You can customize Macroscope's approvability policy. Learn more. |
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.
Overview
Use zero-copy PyZMQ frames for V1 env-server responses and pool relays. The wire protocol, request routing, health handling, and response serialization remain unchanged; the PR only changes the two production transport files.
Why
Large training traces are already materialized once by msgpack. The previous transport path then copied the full payload when the worker server queued its response, copied it again when the pool received it as Python bytes, and copied it once more when the pool forwarded it to the client. Those payload-sized copies consume event-loop time, memory bandwidth, and transient RSS at the point where completed rollouts converge.
Changes
copy=False, allowing PyZMQ to retain the immutable buffer until libzmq finishes with it.zmq.Frameobjects in the pool.copy=False.Performance
A TCP loopback benchmark queued one 128 MiB response and measured the critical send/relay section plus process RSS after the queue settled. Each mode ran three times; the table reports medians.
The remaining RSS is common receiver-side queue storage in the same-process benchmark. The removed portion is the avoidable payload duplication at the PyZMQ API boundaries. Small frames continue to follow PyZMQ's copy-threshold behavior.
Note
Low Risk
Transport-only optimization with no protocol or routing logic changes; relies on PyZMQ buffer lifetime semantics for
copy=False, which is standard for large frames.Overview
Large msgpack rollout responses no longer get copied at the PyZMQ send/recv boundaries on the v1 env server and worker pool.
EnvServersends the packed response withcopy=False, so libzmq can hold the immutable msgpack buffer until the send completes.EnvServerPoolreceives worker replies withcopy=False(aszmq.Frames), uses onlyrequest_id.bytesfor thependinglookup, and relaysrequest_idand the payload frame to the client ROUTER withcopy=False. Request routing, health handling, and serialization are unchanged.Reviewed by Cursor Bugbot for commit 5dbdb5d. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Use zero-copy ZMQ multipart message relay in broker and server
Switches ZMQ recv/send calls in the broker loop and server request handler to use
copy=False, avoiding buffer copies when receiving and forwarding multipart messages.recv_multipart(copy=False)and forwards viasend_multipart(..., copy=False); pending lookup usesrequest_id.bytessincerequest_idis now azmq.Frame.send_multipart(..., copy=False)to avoid copying the payload frame.Macroscope summarized 5dbdb5d.