ss77892 opened a new pull request, #11874: URL: https://github.com/apache/ozone/pull/11874
## What changes were proposed in this pull request? `XceiverClientGrpc` serves blocking calls (`sendCommand`, used by `ReadChunk`, `GetBlock`, `PutBlock` from the standalone client, etc.) on top of the async gRPC stub. Two costs come with that on every request: 1. The reply is delivered on gRPC's shared executor. The response is parsed and the `CompletableFuture` is completed on a pool thread, which then has to wake up the caller blocked in `get()`. Every request pays a thread hand-off and the context switches that go with it. 2. A new bi-directional stream is opened and closed for each request, which adds HTTP/2 stream setup and teardown (HEADERS / END_STREAM frames, call object allocation) to every round trip. This PR removes both for the common case: an untraced blocking call (tracing is off by default in production). **Reply on the waiting thread.** A new `CallerRunsReplyFuture` is both the reply future and the gRPC call executor. gRPC queues the call's callbacks on it, and the thread waiting in `get()` runs them, so the response is parsed and the future completed on the caller. This is the same approach gRPC's own blocking stubs use (`ThreadlessExecutor`). Once the waiter returns (reply, timeout, interrupt), queued and later callbacks run directly, so nothing is left behind. **Pooled streams.** Untraced blocking calls lease a `PooledStream` from a per-channel pool instead of opening a new stream. A stream carries one request at a time; the datanode serves the requests of a stream in order and replies to each, so the next reply always belongs to the current request and no request IDs are needed. After the reply the stream goes back to the pool before the semaphore permit is released. - The pool never holds more streams than the requests in flight, which the client semaphore already bounds. - A pooled stream has no gRPC deadline, so the waiter enforces the request timeout itself and fails the call with `DEADLINE_EXCEEDED`, as a per-call deadline would. - A request that times out, whose waiter is interrupted, or that fails, cancels its stream; the stream is dropped from the pool. - Idle streams are half-closed when the channel leaves `READY` (e.g. the datanode sends GOAWAY on shutdown), so they do not hold up the datanode's graceful shutdown. ## What is the link to the Apache JIRA https://issues.apache.org/jira/browse/HDDS-17561 ## How was this patch tested? UT Benchmark result: [build_comparison_20261030_211225.pdf](https://github.com/user-attachments/files/34209863/build_comparison_20261030_211225.pdf) -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected] --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
