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

[SR-15076] AsyncStream.Continuation.YieldResult is hard to use to implement backpressure #57402

Open
Lukasa opened this issue Aug 16, 2021 · 2 comments
Labels
improvement standard library Area: Standard library umbrella

Comments

@Lukasa
Copy link
Contributor

Lukasa commented Aug 16, 2021

Previous ID SR-15076
Radar rdar://problem/81980766
Original Reporter @Lukasa
Type Improvement
Additional Detail from JIRA
Votes 2
Component/s Standard Library
Labels Improvement
Assignee None
Priority Medium

md5: a8ee54f92c5ada6649ec437f217b0051

Issue Description:

AsyncStream.Continuation.YieldResult exists in no small part to help implement backpressure. It seems designed to let users respond to slow consumption of a buffered stream.

Unfortunately, it's not really possible to take action based on the return value if you cannot tolerate data loss. In particular, .enqueued(remaining: 0) is a particularly tricky return value. This value signals that the next call to yield may return .dropped.

The problem is that the user of AsyncStream cannot take any action in the face of this return value. There appears to be no way to wait for this situation to resolve itself. As a result, users are forced to essentially sleep for some period of time and then optimistically try again. This either burns CPU (if we poll too frequently) or increases latency (if we poll too infrequently).

This leaves the only backpressure-aware option on AsyncStream as the init(unfolding:onCancellation: model. Unfortunately, this init uses "pull-based" backpressure, where an async function is called whenever there is space. If the user is holding an AsyncSequence of their own then they are forced to manually hold the AsyncIterator in order to implement this.

It would be nice to have a complementary API to the return values of yield that lets us wait until we can be confident that yielding a value is likely to succeed.

@ktoso
Copy link
Member

ktoso commented Aug 16, 2021

@swift-ci create

@ktoso
Copy link
Member

ktoso commented Aug 16, 2021

It may be possible to augment this API with an async yield counterpart that would allow suspending until space is available in the buffer...

This limitation came up in real API design in the http client over here: swift-server/async-http-client#406 and if i remember correctly we had discussed it as well during the review of the type's initial introduction. This should be possible to solve on the same type with augmenting its functionality hopefully

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
improvement standard library Area: Standard library umbrella
Projects
None yet
Development

No branches or pull requests

2 participants