Release intercepted request bodies before inference - #1818
Merged
Conversation
Contributor
ApprovabilityVerdict: Approved Simple memory optimization that releases raw request bytes after JSON parsing completes. The parsed body is retained; only the redundant raw bytes are freed earlier to reduce memory pressure during model inference. 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
Release aiohttp's cached intercepted request bytes immediately after JSON parsing, instead of retaining the serialized body for the duration of model inference.
Why
request.read()is the correct ingestion path because it enforces aiohttp's configured request-size limit, but it also stores the complete body inrequest._read_bytes. The handler'srawlocal aliases that allocation, while parsing creates a separate Python object graph. Because the async handler remains suspended during inference, the serialized bytes otherwise stay live alongside the parsed request for the longest part of the request lifecycle.For large prompts or tool results, this avoidably doubles the live payload representation and compounds across concurrent rollouts.
Implementation
After either the primary
pydantic_core.from_jsonparse or the stdlib fallback succeeds, the handler:request._read_bytes = None;rawalias before entering dialect handling or inference.The code deliberately keeps
request.read(), preserving the existing size guard. Downstream code operates on the parsed body and does not reread the request stream.Performance
A PEP 723 microbenchmark ran five interleaved old/new subprocesses with a 64 MiB JSON content value (67,108,878 wire bytes), using a real aiohttp
Request.read()andpydantic_core.from_json.request.read()This is a retained-memory optimization rather than a throughput optimization. Peak parsing memory remains essentially unchanged because the raw and parsed forms must briefly coexist; the benefit is that the raw form no longer survives the potentially long inference wait.
Note
Low Risk
Small lifecycle change in one handler after successful parse; relies on aiohttp’s
_read_bytescache but does not alter auth, inference, or response paths.Overview
Frees intercepted chat-completion request memory sooner by dropping aiohttp’s cached wire body and the local
rawbuffer immediately after JSON parsing inhandle_request, instead of keeping both alongside the parsedbodythrough model inference and user-simulator loops.The handler still uses
request.read()so the existing 1 GiBclient_max_sizeguard is unchanged; only the parsed dict is used downstream.Reviewed by Cursor Bugbot for commit bc81f93. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Release intercepted request body from memory before inference
In
InterceptionServer.handle_requestin server.py, after parsing the raw request body, the handler now setsrequest._read_bytestoNoneand deletes the localrawreference. This reduces memory retention of the wire body during inference processing.Macroscope summarized bc81f93.