Skip to content

Add FiberScheduler::splice - #120

Open
alexey-milovidov wants to merge 1 commit into
mainfrom
splice-io-operation
Open

Add FiberScheduler::splice#120
alexey-milovidov wants to merge 1 commit into
mainfrom
splice-io-operation

Conversation

@alexey-milovidov

@alexey-milovidov alexey-milovidov commented Aug 14, 2026

Copy link
Copy Markdown
Member

FiberScheduler::splice submits IORING_OP_SPLICE in the same blocking and async forms as read, write and accept, so a fiber can move bytes between two descriptors entirely inside the kernel. As with splice(2) one of the two descriptors must be a pipe, which means a relay between two sockets goes socket -> pipe -> socket and never copies the payload into user space.

This is what the ClickHouse proxy uses to forward plaintext connections: ClickHouse/ClickHouse#110105. With the copy relay the bulk HTTP throughput of the proxy was bounded by the user-space buffer size (845 MB/s at a 16 KiB buffer); after switching those legs to splice it reaches ~5 GB/s, matching a direct connection to the backend, and the added per-query latency is unchanged. TLS-terminating legs keep the copy path since their bytes have to be decrypted in user space.

The test relays a payload from one socket to another through a pipe, over the blocking overload for the first leg and the async one for the second, and checks that a source whose peer has shut down reports end of input as zero bytes moved. ./bb test -R FiberIo passes locally in the debug build and under all four sanitizers (address, memory, thread, undefined).

The change is currently carried on the add-splice-op branch, which the ClickHouse pull request pins; once this is merged and clickhouse-public is rebuilt, that pull request will re-pin the submodule to the generated commit.

Submit IORING_OP_SPLICE in the same blocking and async forms as read, write and accept. Splice moves bytes between two descriptors inside the kernel; as in splice(2) one of them must be a pipe, so a caller relaying a stream between two sockets forwards it through an intermediate pipe, with no user-space copy and no dependence on a user-space buffer size. A zero in bytesSpliced means the source reached end of input. The test relays a payload from one socket to another through a pipe over both forms of the call and checks the end-of-input result.
@praktika-gh

praktika-gh Bot commented Aug 14, 2026

Copy link
Copy Markdown

Workflow [PR], commit [675c076]

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