Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new ChannelOption to get the amount of buffered outbound data in the Channel #2849

Merged
merged 27 commits into from
Sep 23, 2024

Conversation

johnnzhou
Copy link
Contributor

@johnnzhou johnnzhou commented Aug 20, 2024

Add ability to get the amount of buffered outbound data from Channel

Motivation:

Right now, SwiftNIO does not have the API to answer the question "how much data is buffered in the Channel". Applications focusing on performance may need to fine-tune the amount of outbound data that will be sent to optimize data throughput, adjust sending rate to avoid overflow, and potentially reduce latency.

SwiftNIO currently provides some backpressure mechanism. This new API will be a good addition. By knowing how much data is buffered directly, applications can make informed decision to adjust for optimal buffer sizes and send rates.

Modifications:

  • Expose current buffer size through ChannelOptions so that users can read the value out. StreamSocketChannel, DatagramSocketChannel, EmbeddedChannel, and AsyncTestingChannel have the same API interface.
  • Various modifications to the existing tests to make sure the new API is working correctly.
  • Add a new so_sndbuf socket option so that users can easily adjust the send buffer size.

Result:

Users can get the amount of outbound bytes currently buffered in the Channel through the new BufferedWritableBytesOption channel option.

Copy link
Contributor

@Lukasa Lukasa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this, it generally looks good! Can you add support for the new channel option in EmbeddedChannel and AsyncTestingChannel as well? It should only behave sensibly when the buffered data is ByteBuffer, so runtime type assertions there are fine.

While we're here, it's worth calling out that this is an incomplete solution, as there may be ChannelHandlers that have also buffered some bytes. This is a very useful building block, but we may want to revisit this space to add more fully-featured functionality for this.

Sources/NIOCore/ChannelOption.swift Outdated Show resolved Hide resolved
@johnnzhou
Copy link
Contributor Author

johnnzhou commented Aug 21, 2024

Hi @Lukasa,

While we're here, it's worth calling out that this is an incomplete solution, as there may be ChannelHandlers that have also buffered some bytes. This is a very useful building block, but we may want to revisit this space to add more fully-featured functionality for this.

thanks for bringing it up. I'm planning to follow our discussion here to add a new protocol that audits the outbound buffered bytes. Anyone who's interested in is also welcome to contribute :). I will fix the comments ASAP.

Copy link
Contributor

@Lukasa Lukasa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool, one quick note, can we get tests for the EmbeddedChannel and AsyncTestingChannel implementations?

@johnnzhou
Copy link
Contributor Author

Sure. Actually I'm working on the tests - should be ready soon. Thanks for the reminder!

@weissi
Copy link
Member

weissi commented Aug 23, 2024

Super cool, thanks @johnnzhou !!

@johnnzhou johnnzhou requested a review from Lukasa August 27, 2024 06:30
@johnnzhou
Copy link
Contributor Author

Hi @Lukasa, whenever you are available, could you take a look at the code change. Appreciate your time and help in advance!

@johnnzhou
Copy link
Contributor Author

johnnzhou commented Sep 3, 2024

Hi @Lukasa @weissi, thanks for the help refining my PR. I think it is ready now. Whenever you have a moment, could you please review the change? Your feedback is greatly appreciated! Thanks for your time!

@Lukasa Lukasa added the semver/minor Adds new public API. label Sep 16, 2024
Copy link
Contributor

@Lukasa Lukasa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice patch @johnnzhou, thank you so much and sorry for the delay.

@Lukasa Lukasa enabled auto-merge (squash) September 16, 2024 13:24
@johnnzhou
Copy link
Contributor Author

johnnzhou commented Sep 16, 2024

Thanks @Lukasa for the review! I synced the PR with the main. It requires maintainer approval to kick off the pipeline. If you are available, can you help rerun the pipeline? Thanks!

part 2 of this feature is also on its way.

auto-merge was automatically disabled September 17, 2024 18:18

Head branch was pushed to by a user without write access

@Lukasa Lukasa enabled auto-merge (squash) September 23, 2024 07:36
auto-merge was automatically disabled September 23, 2024 08:12

Head branch was pushed to by a user without write access

@johnnzhou
Copy link
Contributor Author

Hi @Lukasa,

Thank you for consistently monitoring this PR. I noticed that the latest pipeline failed on the formatting check again - my apologies. I’ve updated the PR based on the pipeline results. Whenever you have a moment, could you please review it and run the workflow again? I really appreciate your time and help!

Thanks so much!

Copy link
Contributor

@Lukasa Lukasa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No problem!

@Lukasa Lukasa enabled auto-merge (squash) September 23, 2024 09:45
@Lukasa Lukasa merged commit ac6d905 into apple:main Sep 23, 2024
28 of 29 checks passed
cgrindel-self-hosted-renovate bot referenced this pull request in cgrindel/rules_swift_package_manager Sep 25, 2024
This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [apple/swift-nio](https://redirect.github.com/apple/swift-nio) | minor
| `2.72.0` -> `2.73.0` |

---

### Release Notes

<details>
<summary>apple/swift-nio (apple/swift-nio)</summary>

###
[`v2.73.0`](https://redirect.github.com/apple/swift-nio/releases/tag/2.73.0)

[Compare
Source](https://redirect.github.com/apple/swift-nio/compare/2.72.0...2.73.0)

<!-- Release notes generated using configuration in .github/release.yml
at main -->

#### What's Changed

##### SemVer Minor

- Make `ByteBuffer`'s description more useful by
[@&#8203;supersonicbyte](https://redirect.github.com/supersonicbyte) in
[https://github.com/apple/swift-nio/pull/2864](https://redirect.github.com/apple/swift-nio/pull/2864)
- Expose `UDP_MAX_SEGMENTS` via System by
[@&#8203;rnro](https://redirect.github.com/rnro) in
[https://github.com/apple/swift-nio/pull/2891](https://redirect.github.com/apple/swift-nio/pull/2891)
- Add new `ChannelOption` to get the amount of buffered outbound data in
the Channel by
[@&#8203;johnnzhou](https://redirect.github.com/johnnzhou) in
[https://github.com/apple/swift-nio/pull/2849](https://redirect.github.com/apple/swift-nio/pull/2849)
- Add an `AcceptBackoffHandler` to the async server bootstraps by
[@&#8203;FranzBusch](https://redirect.github.com/FranzBusch) in
[https://github.com/apple/swift-nio/pull/2782](https://redirect.github.com/apple/swift-nio/pull/2782)

##### SemVer Patch

- Adding a nicer description for `WebSocketFrame` by
[@&#8203;supersonicbyte](https://redirect.github.com/supersonicbyte) in
[https://github.com/apple/swift-nio/pull/2862](https://redirect.github.com/apple/swift-nio/pull/2862)
- Improving `description` and adding `debugDescription` to `NIOAny` by
[@&#8203;supersonicbyte](https://redirect.github.com/supersonicbyte) in
[https://github.com/apple/swift-nio/pull/2866](https://redirect.github.com/apple/swift-nio/pull/2866)
- Make FileChunk sendable by
[@&#8203;ali-ahsan-ali](https://redirect.github.com/ali-ahsan-ali) in
[https://github.com/apple/swift-nio/pull/2871](https://redirect.github.com/apple/swift-nio/pull/2871)
- Make `ByteBuffer.debugDescription` suitable for structural display by
[@&#8203;dnadoba](https://redirect.github.com/dnadoba) in
[https://github.com/apple/swift-nio/pull/2495](https://redirect.github.com/apple/swift-nio/pull/2495)
- Add support for WASILibc by
[@&#8203;MaxDesiatov](https://redirect.github.com/MaxDesiatov) in
[https://github.com/apple/swift-nio/pull/2671](https://redirect.github.com/apple/swift-nio/pull/2671)
- `NIOSingleStepByteToMessageDecoder` reentrancy safety by
[@&#8203;rnro](https://redirect.github.com/rnro) in
[https://github.com/apple/swift-nio/pull/2881](https://redirect.github.com/apple/swift-nio/pull/2881)
- Adopt `NIOThrowingAsyncSequenceProducer` by
[@&#8203;rnro](https://redirect.github.com/rnro) in
[https://github.com/apple/swift-nio/pull/2879](https://redirect.github.com/apple/swift-nio/pull/2879)
- Clamp buffer to maximum upon large write operation by
[@&#8203;ali-ahsan-ali](https://redirect.github.com/ali-ahsan-ali) in
[https://github.com/apple/swift-nio/pull/2745](https://redirect.github.com/apple/swift-nio/pull/2745)
- Revert "Adopt `NIOThrowingAsyncSequenceProducer`
([#&#8203;2879](https://redirect.github.com/apple/swift-nio/issues/2879))"
by [@&#8203;rnro](https://redirect.github.com/rnro) in
[https://github.com/apple/swift-nio/pull/2892](https://redirect.github.com/apple/swift-nio/pull/2892)
- Add concrete description for `EmbeddedEventLoop` by
[@&#8203;aryan-25](https://redirect.github.com/aryan-25) in
[https://github.com/apple/swift-nio/pull/2890](https://redirect.github.com/apple/swift-nio/pull/2890)
- Conditionally include linux/udp.h by
[@&#8203;rnro](https://redirect.github.com/rnro) in
[https://github.com/apple/swift-nio/pull/2894](https://redirect.github.com/apple/swift-nio/pull/2894)
- Work around a type checking error when using the Static Linux SDK by
[@&#8203;euanh](https://redirect.github.com/euanh) in
[https://github.com/apple/swift-nio/pull/2898](https://redirect.github.com/apple/swift-nio/pull/2898)

##### Other Changes

- \[CI] Run tests on push to main by
[@&#8203;FranzBusch](https://redirect.github.com/FranzBusch) in
[https://github.com/apple/swift-nio/pull/2868](https://redirect.github.com/apple/swift-nio/pull/2868)
- \[CI] License header support `.in` and `.cmake` files by
[@&#8203;FranzBusch](https://redirect.github.com/FranzBusch) in
[https://github.com/apple/swift-nio/pull/2870](https://redirect.github.com/apple/swift-nio/pull/2870)
- Include nanoseconds in assertion of timestamp for NIOFileSystem tests
by [@&#8203;gjcairo](https://redirect.github.com/gjcairo) in
[https://github.com/apple/swift-nio/pull/2869](https://redirect.github.com/apple/swift-nio/pull/2869)
- Correct the link of sswg-security at SECURITY.md by
[@&#8203;lamtrinhdev](https://redirect.github.com/lamtrinhdev) in
[https://github.com/apple/swift-nio/pull/2872](https://redirect.github.com/apple/swift-nio/pull/2872)
- Speculative fix for flakey AsyncTestingEventLoop test by
[@&#8203;simonjbeaumont](https://redirect.github.com/simonjbeaumont) in
[https://github.com/apple/swift-nio/pull/2873](https://redirect.github.com/apple/swift-nio/pull/2873)
- ci: Install shellcheck if not present in CI runner by
[@&#8203;simonjbeaumont](https://redirect.github.com/simonjbeaumont) in
[https://github.com/apple/swift-nio/pull/2882](https://redirect.github.com/apple/swift-nio/pull/2882)
- ci: Use ${GITHUB_BASE_REF} as treeish for checking API break by
[@&#8203;simonjbeaumont](https://redirect.github.com/simonjbeaumont) in
[https://github.com/apple/swift-nio/pull/2883](https://redirect.github.com/apple/swift-nio/pull/2883)
- ci: Refer to nested reusable workflows using remote variant by
[@&#8203;simonjbeaumont](https://redirect.github.com/simonjbeaumont) in
[https://github.com/apple/swift-nio/pull/2884](https://redirect.github.com/apple/swift-nio/pull/2884)
- \[CI] Fix pull request label workflow by
[@&#8203;FranzBusch](https://redirect.github.com/FranzBusch) in
[https://github.com/apple/swift-nio/pull/2885](https://redirect.github.com/apple/swift-nio/pull/2885)

#### New Contributors

- [@&#8203;ali-ahsan-ali](https://redirect.github.com/ali-ahsan-ali)
made their first contribution in
[https://github.com/apple/swift-nio/pull/2871](https://redirect.github.com/apple/swift-nio/pull/2871)
- [@&#8203;aryan-25](https://redirect.github.com/aryan-25) made their
first contribution in
[https://github.com/apple/swift-nio/pull/2890](https://redirect.github.com/apple/swift-nio/pull/2890)
- [@&#8203;johnnzhou](https://redirect.github.com/johnnzhou) made their
first contribution in
[https://github.com/apple/swift-nio/pull/2849](https://redirect.github.com/apple/swift-nio/pull/2849)
- [@&#8203;euanh](https://redirect.github.com/euanh) made their first
contribution in
[https://github.com/apple/swift-nio/pull/2898](https://redirect.github.com/apple/swift-nio/pull/2898)

**Full Changelog**:
apple/swift-nio@2.72.0...2.73.0

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get
[config
help](https://redirect.github.com/renovatebot/renovate/discussions) if
that's undesired.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Renovate
Bot](https://redirect.github.com/renovatebot/renovate).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC45NC4xIiwidXBkYXRlZEluVmVyIjoiMzguOTQuMSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Co-authored-by: cgrindel-self-hosted-renovate[bot] <139595543+cgrindel-self-hosted-renovate[bot]@users.noreply.github.com>
Lukasa added a commit that referenced this pull request Oct 30, 2024
…nel handler (#2918)

Add new protocol to get buffered bytes from `ChannelHandler`s and
`ChannelPipeline` API to query the buffered bytes from `ChannelHandler`s

### Motivation:

In #2849, a new `ChannelOption` is introduced to retrieve the number of
buffered outbound bytes in a `Channel`. However, this solution does not
account for bytes that may be buffered within individual
`ChannelHandler`s. This PR builds on #2849 by adding functionality to
audit buffered bytes residing in `ChannelHandler`s and exposing this
information through new `ChannelPipeline` APIs.

### Modifications:

- Two new protocols for `ChannelHandler` to audit buffered bytes for
inbound and outbound.
    - `NIOOutboundByteBufferingChannelHandler`
    - `NIOInboundByteBufferingChannelHandler`
- New `ChannelPipeline` APIs
    - outboundBufferedBytes()
- outboundBufferedBytes(in: ChannelHandlerContext) (only in
`syncOperations`)
    - inboundBufferedBytes()
- inboundBufferedBytes(in: ChannelHandlerContext) (only in
`syncOperations`)

### Result:

Users can now easily query the amount of bytes buffered in
`ChannelHandler`s using the new `ChannelPipeline` APIs, enhancing the
visibility of `ChannelHandler` performance.

---------

Co-authored-by: Cory Benfield <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
semver/minor Adds new public API.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants