Skip to content

Optimize /solve request serialization in autopilot#4159

Open
MartinquaXD wants to merge 2 commits intomainfrom
stream-http-body-only-once
Open

Optimize /solve request serialization in autopilot#4159
MartinquaXD wants to merge 2 commits intomainfrom
stream-http-body-only-once

Conversation

@MartinquaXD
Copy link
Contributor

Description

Currently the way the autopilot serializes /solve requests is still sub optimal. While it does indeed only serialize the /solve requests once it still allocates memory for every HTTP request it ultimately sends.
Since reqwest also supports Bytes as the request body which are already references counted we can save a bunch of allocating and copying data by serializing the auction data into a Bytes instance and cloning that into the individual /solve HTTP requests.

Changes

  • changes internal members of solve::Request from serde_json::RawValue to Bytes
  • adds a new X-Auction-Id header which is important for another optimization but that has to be merged before said optimization
  • moved original serialization from the executor thread to a background task that's intended for blocking operations since serialization takes quite a bit of time

How to test

existing e2e tests

@MartinquaXD MartinquaXD requested a review from a team as a code owner February 15, 2026 15:38
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request optimizes /solve request serialization by using Bytes to avoid repeated allocations and copies, and moves serialization to a blocking task. This is a good performance improvement. I have found one high-severity issue related to potential panics and inefficiencies in tracing/logging code that could affect service stability and performance.

Comment on lines 192 to 195
fn body_to_string(&self) -> Cow<'_, str> {
let serialized = serde_json::to_string(&self).unwrap();
Cow::Owned(serialized)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Using .unwrap() on the result of serde_json::to_string can cause a panic if serialization fails. In a tracing context, this can crash the service, creating a potential denial-of-service vulnerability. It is safer to handle this error gracefully, as shown in the suggestion. Furthermore, serializing data to JSON and then immediately parsing it back into a serde_json::Value within the same operation is inefficient. For tracing, consider using a tracing::field::Visit implementation to directly collect fields into a serde_json::Map to avoid unnecessary serialization/deserialization cycles, which is a more robust and efficient approach for this context.

    fn body_to_string(&self) -> Cow<'_, str> {
        match serde_json::to_string(self) {
            Ok(serialized) => Cow::Owned(serialized),
            Err(_) => Cow::Borrowed("<failed to serialize body>"),
        }
    }
References
  1. Avoid serializing data to JSON and then immediately parsing it back into a serde_json::Value within the same operation, as this is inefficient and can impact performance. Instead, consider using a tracing::field::Visit implementation to directly collect fields into a serde_json::Map to avoid unnecessary serialization/deserialization cycles.

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.

2 participants