Skip to content

Conversation

@ardatan
Copy link
Member

@ardatan ardatan commented Jul 1, 2025

Avoid cloning variables and operation string(aka query) for subgraph requests

@ardatan ardatan requested a review from kamilkisiela July 1, 2025 14:36
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.

Summary of Changes

Hello @ardatan, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request primarily focuses on optimizing the performance of GraphQL request processing, especially for calls made to subgraphs. It achieves this by refactoring internal data structures to minimize memory allocations and data cloning, ensuring that query strings, operation names, and variables are passed by reference where possible. Additionally, it includes general improvements to the query projection logic to further reduce allocations and refines the gateway's handling of incoming requests.

Highlights

  • Reduced Allocations for Subgraph Requests: I've introduced a new SubgraphExecutionRequest struct that utilizes borrowed data (&str, &Value) for query strings, operation names, and variables. This change significantly reduces memory allocations and data cloning when preparing and executing requests against subgraphs, leading to improved performance.
  • Improved Subgraph Executor Interface: The SubgraphExecutor trait and its various implementations (e.g., for HTTP and async-graphql executors) have been updated to accept the new, more efficient SubgraphExecutionRequest type, ensuring that all subgraph communication benefits from the reduced allocation strategy.
  • Gateway Request Type Refactoring: The ExecutionRequest struct, which represents incoming GraphQL requests at the gateway level, has been redefined and isolated within bin/gateway/src/pipeline/graphql_request_params.rs. This clarifies the separation between the gateway's external request handling and the internal subgraph execution logic.
  • Optimized Query Projection: I've refactored several functions within the query projection logic (lib/query-plan-executor/src/projection.rs) to operate on immutable references and eliminate unnecessary string allocations. These general improvements contribute to overall performance gains beyond just subgraph requests.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist is currently in preview and may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments to provide feedback.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@github-actions
Copy link

github-actions bot commented Jul 1, 2025

Federation Audit Results

188 tests  ±0   177 ✅ ±0   3s ⏱️ ±0s
 41 suites ±0     0 💤 ±0 
 41 files   ±0    11 ❌ ±0 

For more details on these failures, see this check.

Results for commit 5c02b42. ± Comparison against base commit 7b6ac07.

♻️ This comment has been updated with latest results.

@github-actions
Copy link

github-actions bot commented Jul 1, 2025

TestsPassed ☑️SkippedFailed ❌️Time ⏱
federation-audit | abstract-types.xml18 ran13 ✅5 ❌509ms
federation-audit | child-type-mismatch.xml4 ran1 ✅3 ❌135ms
federation-audit | circular-reference-interface.xml2 ran1 ✅1 ❌48ms
federation-audit | complex-entity-call.xml1 ran1 ✅84ms
federation-audit | corrupted-supergraph-node-id.xml10 ran8 ✅2 ❌142ms
federation-audit | enum-intersection.xml5 ran5 ✅72ms
federation-audit | fed1-external-extends-resolvable.xml1 ran1 ✅30ms
federation-audit | fed1-external-extends.xml4 ran4 ✅65ms
federation-audit | fed1-external-extension.xml4 ran4 ✅65ms
federation-audit | fed2-external-extends.xml4 ran4 ✅68ms
federation-audit | fed2-external-extension.xml4 ran4 ✅66ms
federation-audit | include-skip.xml4 ran4 ✅89ms
federation-audit | input-object-intersection.xml3 ran3 ✅37ms
federation-audit | interface-object-with-requires.xml7 ran7 ✅118ms
federation-audit | keys-mashup.xml1 ran1 ✅31ms
federation-audit | mutations.xml4 ran4 ✅79ms
federation-audit | mysterious-external.xml2 ran2 ✅53ms
federation-audit | nested-provides.xml2 ran2 ✅34ms
federation-audit | node.xml1 ran1 ✅26ms
federation-audit | non-resolvable-interface-object.xml7 ran7 ✅77ms
federation-audit | null-keys.xml1 ran1 ✅31ms
federation-audit | override-type-interface.xml4 ran4 ✅72ms
federation-audit | override-with-requires.xml4 ran4 ✅90ms
federation-audit | parent-entity-call-complex.xml1 ran1 ✅35ms
federation-audit | parent-entity-call.xml1 ran1 ✅29ms
federation-audit | provides-on-interface.xml2 ran2 ✅45ms
federation-audit | provides-on-union.xml2 ran2 ✅43ms
federation-audit | requires-interface.xml5 ran5 ✅77ms
federation-audit | requires-requires.xml5 ran5 ✅107ms
federation-audit | requires-with-argument.xml5 ran5 ✅104ms
federation-audit | requires-with-fragments.xml6 ran6 ✅97ms
federation-audit | shared-root.xml2 ran2 ✅44ms
federation-audit | simple-entity-call.xml1 ran1 ✅24ms
federation-audit | simple-inaccessible.xml4 ran4 ✅54ms
federation-audit | simple-interface-object.xml13 ran13 ✅184ms
federation-audit | simple-override.xml2 ran2 ✅36ms
federation-audit | simple-requires-provides.xml12 ran12 ✅204ms
federation-audit | typename.xml6 ran6 ✅74ms
federation-audit | unavailable-override.xml2 ran2 ✅33ms
federation-audit | union-interface-distributed.xml10 ran10 ✅113ms
federation-audit | union-intersection.xml12 ran12 ✅162ms

@github-actions
Copy link

github-actions bot commented Jul 1, 2025

GraphQL over HTTP Audit Results

61 tests  ±0   61 ✅ ±0   0s ⏱️ ±0s
 1 suites ±0    0 💤 ±0 
 1 files   ±0    0 ❌ ±0 

Results for commit 5c02b42. ± Comparison against base commit 7b6ac07.

♻️ This comment has been updated with latest results.

@ardatan ardatan force-pushed the avoid_extra_allocation branch from e808033 to ca72f46 Compare July 1, 2025 14: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 introduces the SubgraphExecutionRequest to avoid extra allocation/clone in subgraph requests. The changes are well-propagated through the executor implementations. There are a few suggestions for better maintainability and readability.

@ardatan ardatan force-pushed the avoid_extra_allocation branch from ca72f46 to 5c02b42 Compare July 1, 2025 14:40
@github-actions
Copy link

github-actions bot commented Jul 1, 2025

k6-benchmark results

     ✓ response code was 200
     ✓ no graphql errors
     ✓ valid response structure

     █ setup

     checks.........................: 100.00% ✓ 8115      ✗ 0   
     data_received..................: 239 MB  7.9 MB/s
     data_sent......................: 3.2 MB  106 kB/s
     http_req_blocked...............: avg=73.86µs  min=1.64µs   med=4.52µs   max=6.19ms   p(90)=6.79µs   p(95)=8.32µs  
     http_req_connecting............: avg=67.98µs  min=0s       med=0s       max=6.13ms   p(90)=0s       p(95)=0s      
     http_req_duration..............: avg=108.06ms min=4.47ms   med=97.45ms  max=440.44ms p(90)=165.24ms p(95)=194.23ms
       { expected_response:true }...: avg=108.06ms min=4.47ms   med=97.45ms  max=440.44ms p(90)=165.24ms p(95)=194.23ms
     http_req_failed................: 0.00%   ✓ 0         ✗ 2725
     http_req_receiving.............: avg=1.5ms    min=36.01µs  med=68.95µs  max=112.05ms p(90)=651.61µs p(95)=2.13ms  
     http_req_sending...............: avg=397.86µs min=9.22µs   med=21.73µs  max=130.36ms p(90)=99.17µs  p(95)=1.13ms  
     http_req_tls_handshaking.......: avg=0s       min=0s       med=0s       max=0s       p(90)=0s       p(95)=0s      
     http_req_waiting...............: avg=106.15ms min=4.39ms   med=95.85ms  max=429.39ms p(90)=160.55ms p(95)=186.19ms
     http_reqs......................: 2725    90.108164/s
     iteration_duration.............: avg=556.04ms min=101.12ms med=542.39ms max=1s       p(90)=664.63ms p(95)=723.41ms
     iterations.....................: 2705    89.446819/s
     vus............................: 50      min=50      max=50
     vus_max........................: 50      min=50      max=50

@ardatan ardatan force-pushed the avoid_extra_allocation branch 2 times, most recently from 5308c5e to 80a25ea Compare July 1, 2025 14:48
// We may want to remove it, but let's see.
let mut body = String::with_capacity(4096);
body.push_str("{\"query\":");
write_and_escape_string(&mut body, execution_request.query);
Copy link
Member

Choose a reason for hiding this comment

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

nice!

let mut body =
"{\"query\":".to_string() + &serde_json::to_string(&execution_request.query).unwrap();
// We may want to remove it, but let's see.
let mut body = String::with_capacity(4096);
Copy link
Member

Choose a reason for hiding this comment

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

4096 is generally enough? how did we end up with this value?

Copy link
Contributor

Choose a reason for hiding this comment

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

guess

Copy link
Contributor

Choose a reason for hiding this comment

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

it will never be correct

Copy link
Member

@dotansimha dotansimha left a comment

Choose a reason for hiding this comment

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

lgtm. @kamilkisiela please review as well.

@ardatan ardatan force-pushed the avoid_extra_allocation branch from 80a25ea to a5d0ef0 Compare July 2, 2025 13:37
Base automatically changed from parallelism to fix-simple-interface-object July 2, 2025 14:11
@ardatan ardatan force-pushed the avoid_extra_allocation branch from a5d0ef0 to 7d58d87 Compare July 2, 2025 14:13
@ardatan ardatan merged commit 588f47a into fix-simple-interface-object Jul 2, 2025
10 checks passed
@ardatan ardatan deleted the avoid_extra_allocation branch July 2, 2025 14:14
ardatan added a commit that referenced this pull request Jul 2, 2025
Avoid cloning variables and operation string(aka `query`) for subgraph
requests
ardatan added a commit that referenced this pull request Jul 3, 2025
Avoid cloning variables and operation string(aka `query`) for subgraph
requests
ardatan added a commit that referenced this pull request Jul 8, 2025
Avoid cloning variables and operation string(aka `query`) for subgraph
requests
ardatan added a commit that referenced this pull request Jul 8, 2025
Also includes #226 & #229 & #245

---------

Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com>
ardatan added a commit that referenced this pull request Jul 8, 2025
Also includes #226 & #229 & #245

---------

Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com>
ardatan added a commit that referenced this pull request Jul 9, 2025
Also includes #226 & #229 & #245

---------

Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com>
ardatan added a commit that referenced this pull request Jul 16, 2025
Also includes #226 & #229 & #245

---------

Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com>
ardatan added a commit that referenced this pull request Jul 17, 2025
Also includes #226 & #229 & #245

---------

Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com>
ardatan added a commit that referenced this pull request Jul 18, 2025
Also includes #226 & #229 & #245

---------

Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com>
ardatan added a commit that referenced this pull request Jul 21, 2025
Also includes #226 & #229 & #245

---------

Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com>
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.

3 participants