Skip to content

gh-159503: Avoid copying the unsent remainder of a bytes write in asyncio selector transports - #159504

Open
Ar-maan05 wants to merge 1 commit into
python:mainfrom
Ar-maan05:asyncio-write-remainder-copy
Open

Ar-maan05 wants to merge 1 commit into
python:mainfrom
Ar-maan05:asyncio-write-remainder-copy

Conversation

@Ar-maan05

@Ar-maan05 Ar-maan05 commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

When a large bytes write is queued behind pending data, every partial send re-queued the leftover as b[nbytes:], copying the rest of the object each time, so the write cost O(n**2). One write of 48 MiB behind a 2 MiB prefix on a socketpair (Linux, sendmsg path):

before: 1633 ms
after:    14 ms

The fix wraps the remainder in a memoryview in _adjust_leftover_buffer() and _write_send(), the same way write() already does on its first-send path. A bytearray passed to write() now stays exported while its remainder is pending on these paths too, which the first-send path already does today.

Tested with two new tests checking that the leftover is a view on the original object, test_asyncio passing, and a differential harness that drives the old and new methods with a scripted socket (partial sends, BlockingIOError, send and sendmsg, bytes/bytearray/memoryview input): identical output over 1200 runs.

…in asyncio selector transports

When a large bytes write is queued behind pending data, every partial send re-queued the leftover as b[nbytes:], copying the rest of the object each time. Keep the remainder as a memoryview in _adjust_leftover_buffer() and _write_send(), as write() already does on its first-send path.
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.

1 participant