Skip to content

HDDS-17442. Domain socket requests run on the read executor shared with gRPC, where a response write that waits for its reader holds a thread - #11744

Draft
smengcl wants to merge 1 commit into
apache:masterfrom
smengcl:HDDS-17442
Draft

smengcl wants to merge 1 commit into
apache:masterfrom
smengcl:HDDS-17442

Conversation

@smengcl

@smengcl smengcl commented Oct 24, 2026

Copy link
Copy Markdown
Contributor

Generated-by: Claude Code (Opus 5.5)

What changes were proposed in this pull request?

OzoneContainer creates one fixed size read executor (hdds.datanode.read.chunk.threads.per.volume threads per volume) and passes it to both XceiverServerGrpc and XceiverServerDomainSocket. The Receiver of each domain socket connection submits one ProcessRequestTask per request to that executor, with no limit per connection. Each task dispatches its request and then writes the response in Receiver.sendResponse while holding a per connection lock, so a write that waits for its reader (up to the socket send timeout) holds a pool thread, and every other task of that connection that a pool thread picks up waits on the lock. The tasks of one connection can therefore hold every thread of the executor, and gRPC requests and other domain socket connections queue behind them.

This change makes Receiver.run process each request on the connection's own thread instead of the shared executor, so a write that waits for its reader holds only that connection's thread. Receiver and XceiverServerDomainSocket no longer take the executor, and OzoneContainer no longer passes it. The gRPC server is unchanged. There is no configuration or protocol change.

Behaviour change: requests of one domain socket connection are now processed one at a time in arrival order (responses were already written one at a time). A client keeps one such connection per pipeline and sends the GetBlock requests of all its block streams on it, so concurrent GetBlocks from one client to its local datanode are now dispatched one after another. GetBlock only looks up the block metadata and opens the block file, and block data is read locally through the received descriptor, so the effect should be small; it was not measured. The local op in queue latency metric of domain socket requests now reads about 0.

Alternatives considered: a cap on one connection's tasks in the shared executor (several connections can still hold the whole executor, and it needs a new limit); a separate executor for the domain socket server (protects gRPC but not other domain socket clients); dispatching on the shared executor and writing the response on the connection's thread (serializes per connection just the same, with more wiring).

Overlap with other open changes: this removes the executor argument of the XceiverServerDomainSocket constructor, which the new tests of HDDS-17436 and HDDS-17441 pass, and both conflict textually with it in the test imports. Whichever lands second drops the argument or rebases.

What is the link to the Apache JIRA

https://issues.apache.org/jira/browse/HDDS-17442

How was this patch tested?

  • New TestXceiverServerDomainSocket.testUnreadResponsesDoNotDelayOtherConnections: leaves the responses of one connection unread, then requires that a GetBlock on a second connection is answered and that the first connection receives both responses in order once it reads them. Without the change the second GetBlock gets no response within the 5 s read timeout (SocketTimeoutException).
  • TestXceiverServerDomainSocket (15 tests), TestXceiverClientManagerSC, TestLocalChunkInputStream, TestDomainSocketFactory, TestOzoneContainer and TestKeyValueHandler pass locally on macOS; checkstyle is clean. Not run on Linux.

…th gRPC, where a response write that waits for its reader holds a thread

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@smengcl smengcl added the AI-gen label Oct 24, 2026
Copilot AI lite review requested due to automatic review settings October 24, 2026 21:32

Copilot AI left a comment

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.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota.

@ChenSammi

ChenSammi commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

@smengcl , I'm afraid this approach could impact the short-circuit performance with a noticeable degradation. Let me check it with some test.

@ChenSammi

Copy link
Copy Markdown
Contributor

Random read and vector search benchmark
Before the patch
Random access: 2,564 rows/sec
Vector search: 123.4 QPS
nprobes= 1 QPS= 134.6 avg_latency=7.4ms
nprobes= 4 QPS= 142.6 avg_latency=7.0ms
nprobes= 8 QPS= 170.1 avg_latency=5.9ms
nprobes= 16 QPS= 163.0 avg_latency=6.1ms
nprobes= 32 QPS= 132.8 avg_latency=7.5ms

After the patch
Random access: 660 rows/sec
Vector search: 69.2 QPS
nprobes= 1 QPS= 82.1 avg_latency=12.2ms
nprobes= 4 QPS= 81.4 avg_latency=12.3ms
nprobes= 8 QPS= 84.3 avg_latency=11.9ms
nprobes= 16 QPS= 84.6 avg_latency=11.8ms
nprobes= 32 QPS= 74.8 avg_latency=13.4ms

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants