Skip to content

transport: optimize heap allocations in ready reader and update syscall connection handling#9035

Merged
arjan-bal merged 4 commits into
grpc:masterfrom
arjan-bal:optimize-ready-reader
Apr 14, 2026
Merged

transport: optimize heap allocations in ready reader and update syscall connection handling#9035
arjan-bal merged 4 commits into
grpc:masterfrom
arjan-bal:optimize-ready-reader

Conversation

@arjan-bal
Copy link
Copy Markdown
Contributor

@arjan-bal arjan-bal commented Apr 2, 2026

This PR eliminates per-call heap allocations in nonBlockingReader.ReadOnReady().

Previously, calling RawConn.Read with an inline closure caused captured variables (and the closure itself) to escape to the heap. To resolve this, we moved the closure's required state and return values into fields on the nonBlockingReader struct. The state is set before execution, and the results are read afterward. Because the closure now only relies on the receiver's fields, we instantiate it exactly once during nonBlockingReader construction and reuse it, completely avoiding allocations on the hot path.

Additionally, this change updates the types for which non-blocking reads are performed to the following:

  • Unwrapped types created by net.Dial. This avoid reading encrypted data from credentials.syscallConns.
  • Types that already implement the ReadyReader interface themselves to support encrypted connections.

These changes are a prerequisite for #9032.

Benchmarks

#9032 uses nonBlockingReader instead of standard net.Conn.Read and confirms zero increase in heap allocations for streaming RPCs.

RELEASE NOTES: N/A

@arjan-bal arjan-bal added this to the 1.81 Release milestone Apr 2, 2026
@arjan-bal arjan-bal added Type: Performance Performance improvements (CPU, network, memory, etc) Area: Transport Includes HTTP/2 client/server and HTTP server handler transports and advanced transport features. labels Apr 2, 2026
@arjan-bal arjan-bal changed the title transport: optimize ready reader transport: optimize heap allocations in ready reader Apr 2, 2026
@arjan-bal arjan-bal force-pushed the optimize-ready-reader branch from a160ebc to ce2cb88 Compare April 2, 2026 12:41
@arjan-bal arjan-bal requested review from easwars and mbissa April 2, 2026 12:43
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 2, 2026

Codecov Report

❌ Patch coverage is 51.11111% with 22 lines in your changes missing coverage. Please review.
✅ Project coverage is 82.78%. Comparing base (a21508e) to head (138ddfd).
⚠️ Report is 13 commits behind head on master.

Files with missing lines Patch % Lines
internal/transport/readyreader/ready_reader.go 51.11% 11 Missing and 11 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #9035      +/-   ##
==========================================
- Coverage   83.06%   82.78%   -0.28%     
==========================================
  Files         413      413              
  Lines       33135    33404     +269     
==========================================
+ Hits        27523    27655     +132     
- Misses       4199     4258      +59     
- Partials     1413     1491      +78     
Files with missing lines Coverage Δ
internal/transport/readyreader/ready_reader.go 52.45% <51.11%> (-24.69%) ⬇️

... and 34 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@easwars
Copy link
Copy Markdown
Contributor

easwars commented Apr 7, 2026

@arjan-bal : Could the failing test in CI be related to changes here? I haven't seen that test flake anytime recently.

@easwars easwars assigned arjan-bal and unassigned easwars and mbissa Apr 7, 2026
@arjan-bal
Copy link
Copy Markdown
Contributor Author

@arjan-bal : Could the failing test in CI be related to changes here? I haven't seen that test flake anytime recently.

The test was reported in #8993 and a fix was made. I suspect the fix was incomplete so I've re-opened the issue and kept is assigned to the test author.

I don't think the failure is related to the changes in this PR, as the ReadyReader code is currently only used with ALTS. The changes to integrate it into the HTTP/2 framer will happen in multiple follow-up PRs.

@arjan-bal arjan-bal assigned easwars and unassigned arjan-bal Apr 8, 2026
Comment thread internal/transport/readyreader/ready_reader.go
@easwars easwars assigned arjan-bal and unassigned easwars Apr 8, 2026
@arjan-bal arjan-bal changed the title transport: optimize heap allocations in ready reader transport: optimize heap allocations in ready reader and update syscall connection handling Apr 9, 2026
@arjan-bal arjan-bal assigned easwars and unassigned arjan-bal Apr 9, 2026
@arjan-bal
Copy link
Copy Markdown
Contributor Author

/gemini review

Copy link
Copy Markdown
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 the nonBlockingReader by moving per-call state into the struct to avoid heap allocations and refactors the New function to use a specialized newNonBlockingReader constructor. The review feedback highlights that these optimizations introduce thread-safety concerns that need to be documented or addressed, and suggests resetting the internal state after each read to ensure that references can be properly garbage collected.

Comment on lines 48 to 53
type nonBlockingReader struct {
raw syscall.RawConn
// The following fields are stored as field to avoid heap allocations.
state readState
doRead func(fd uintptr) bool
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

The nonBlockingReader struct is no longer thread-safe because it uses shared fields (state) to store per-call request and response parameters to avoid heap allocations. While this is an effective optimization for gRPC's typical single-threaded reader loop, it is a regression in safety compared to the previous implementation. If ReadOnReady is called concurrently from multiple goroutines, it will result in data races and corrupted state. Please document this limitation or ensure that concurrent access is not possible.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

By default, most readers and writers are not thread-safe. They maintain internal state without mutex protection, requiring callers to handle synchronization themselves. Because lack of thread safety is the standard expectation, only implementations that are thread-safe need to document their behavior. For example, none of the exported types in the bufio package mention thread safety: https://pkg.go.dev/bufio#Reader

Comment thread internal/transport/readyreader/ready_reader.go
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
@Pranjali-2501
Copy link
Copy Markdown
Contributor

Pranjali-2501 commented Apr 12, 2026

The test was reported in #8993 and a fix was made. I suspect the fix was incomplete so I've re-opened the issue and kept is assigned to the test author.

Test reported in #8993 is fixed and not flaking any more.

Test Test/ClientStreaming_ClientCallRecvMsgTwice flaking on your PR is different and is Flaky too.

if !ok {
return nil
}
if raw, err := sysConn.SyscallConn(); err == nil {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nit: Handle the error case to reduce the indent in the non-error case.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done.

@easwars easwars assigned arjan-bal and unassigned easwars Apr 13, 2026
@arjan-bal arjan-bal merged commit cdc60df into grpc:master Apr 14, 2026
14 checks passed
@arjan-bal arjan-bal deleted the optimize-ready-reader branch April 14, 2026 06:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area: Transport Includes HTTP/2 client/server and HTTP server handler transports and advanced transport features. Type: Performance Performance improvements (CPU, network, memory, etc)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants