Repository navigation
perf(io): remove expired native channel waiters in constant time - #1671
Open
sebastian-griego wants to merge 1 commit into
Open
sebastian-griego wants to merge 1 commit into
sebastian-griego wants to merge 1 commit into
Conversation
This was referenced Oct 18, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A timed channel operation can delay unrelated IO when it expires behind many blocked operations.
chan_cutscans the channel queue to find the previous waiter. Even when timeouts fire in queue order, removing T timed waiters behind B blocked waiters requires O(B × T) queue traversal on the IO loop.Use the existing
IoWork.prevfield to remove each expired channel waiter in O(1). Maintain both links when a waiter enters the queue, leaves on timeout, or wakes in FIFO order. The waiter and its timer use separateIoWorkobjects, so this adds no allocation or struct field.Add
chan_waiter_links.bendto check sender and receiver queues. It covers head, middle, tail, and singleton removal; enqueue after timeout; wake before timeout; close; and activation reuse. The test checks results without a performance threshold.This targets native IO performance. It is separate from #1250 and #1442, which concern the global poll and timer queues. This change only updates the channel waiter ring.
Measurement
The Base-only program below parks 32,768 blocking senders and then starts 4,096 sends with 100 ms timeouts. A separate fiber sleeps for 100 ms. Every run returned all 4,096 expected timeout results.
Both versions use
-O3and--threads 1. The baseline ise5527d5be0c441d00f1f7d2fb61eb464fa478e5c. The changed binaries use C emitted from this branch. These results measure this workload; global timer insertion costs remain.Validation
Timing reproduction
Save this as
mixed_timeouts.bendin the repository root. Run it on the baseline and this branch: