-
Notifications
You must be signed in to change notification settings - Fork 651
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
Adopt NIOThrowingAsyncSequenceProducer
#2879
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In general this looks good to me. Have you run some benchmarks between the two to make sure we still have the same performance?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good! I left a couple of small comments which need addressing.
@@ -135,52 +136,85 @@ extension DirectoryEntries.Batched.AsyncIterator: Sendable {} | |||
// MARK: - Internal | |||
|
|||
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) | |||
extension BufferedStream where Element == [DirectoryEntry] { | |||
extension NIOThrowingAsyncSequenceProducer where Element == [DirectoryEntry], Failure == Error, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit
extension NIOThrowingAsyncSequenceProducer where Element == [DirectoryEntry], Failure == Error, | |
extension NIOThrowingAsyncSequenceProducer where Element == [DirectoryEntry], Failure == (any Error), |
switch self.state { | ||
case let .idle(handle, _): | ||
return handle.threadPool | ||
case let .open(threadPool, _, _): | ||
return threadPool | ||
case .openPausedProducing(let threadPool, let source, let array): | ||
self.state = .modifying |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.modifying
isn't required here because we aren't modifying any of the state held in the openPausedProducing
case
internal mutating func pauseProducing() { | ||
switch self.state { | ||
case .open(let nIOThreadPool, let source, let array): | ||
self.state = .modifying |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here, no need to do .modifying
case .done: | ||
return nil | ||
case .modifying: | ||
fatalError() | ||
} | ||
} | ||
|
||
internal mutating func pauseProducing() { | ||
switch self.state { | ||
case .open(let nIOThreadPool, let source, let array): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: threadPool
init(range: FileChunks.ChunkRange, handle: SystemFileHandle, length: Int64) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: no blank lines at the start of funcs
init(range: FileChunks.ChunkRange, handle: SystemFileHandle, length: Int64) { | |
init(range: FileChunks.ChunkRange, handle: SystemFileHandle, length: Int64) { |
let state: ProducerState = switch range { | ||
case .entireFile: | ||
.init(handle: handle, range: nil) | ||
case .partial(let partialRange): | ||
.init(handle: handle, range: partialRange) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, I don't think our minimum Swift version is new enough to support this? Also the indentation is way off for the body of each case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Also I really don't like this syntax but maybe I'm just a curmudgeon...)
|
||
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) | ||
extension ProducerState.Producing { | ||
mutating func updateRange(count: Int) -> Bool { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not obvious how the range is updated without looking at the implementation, also the return value is quite misleading: if updateRange(count: blah) { ... }
looks a whole lot like "if the range was updated then ...".
Would probably be clearer if you call this didReadBytes(_ count: Int)
and documented the return value (you could use an enum for the return type but that's probably overkill)
I would be surprised if there was a substantial difference. You'd think the syscalls would dominate here but it's worth doing some validation nonetheless. |
7d74670
to
41fe2de
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good modulo some failing CI!
case .produceMore: | ||
self.produceMore() | ||
case .stopProducing: | ||
self.state.withLockedValue { state in state.pauseProducing()} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
self.state.withLockedValue { state in state.pauseProducing()} | |
self.state.withLockedValue { state in state.pauseProducing() } |
41fe2de
to
b61146f
Compare
Motivation: Adopt `NIOThrowingAsyncSequenceProducer` in NIOFileSystem to reduce code duplication. Modifications: Adopt `NIOThrowingAsyncSequenceProducer` in NIOFileSystem `DirectoryEntryProducer` and `FileChunkProducer` Result: No functional changes. Internal changes reduce code duplication.
b61146f
to
eac6c2a
Compare
Performance-wise there doesn’t seem to be much of a difference. I tested listing the files on disk, exercising the For the existing code: For the new code: |
### Motivation: Adopt `NIOThrowingAsyncSequenceProducer` in NIOFileSystem to reduce code duplication. ### Modifications: Adopt `NIOThrowingAsyncSequenceProducer` in NIOFileSystem `DirectoryEntryProducer` and `FileChunkProducer` ### Result: No functional changes. Internal changes reduce code duplication.
This pull consistently causes hanging I'll see if I can track it down and file an issue. |
This reverts commit 282f593.
This reverts commit 282f593. ### Motivation: Repeated testing in linux containers has surfaced issues with the implementation which require some rethinking of the code, let's revert it for now and fix it up. ### Modifications: Revert the adoption commit. ### Result: The change is backed out.
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 [@​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 [@​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 [@​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 [@​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 [@​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 [@​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 [@​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 [@​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 [@​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 [@​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 [@​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 [@​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` ([#​2879](https://redirect.github.com/apple/swift-nio/issues/2879))" by [@​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 [@​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 [@​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 [@​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 [@​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 [@​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 [@​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 [@​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 [@​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 [@​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 [@​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 [@​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 [@​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 - [@​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) - [@​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) - [@​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) - [@​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>
### Motivation: Adopt `NIOThrowingAsyncSequenceProducer` in NIOFileSystem to reduce code duplication. ### Modifications: Adopt `NIOThrowingAsyncSequenceProducer` in NIOFileSystem `DirectoryEntryProducer` and `FileChunkProducer`. This change was previously merged and then backed out due to issues (#2879). The original change is in the first commit, the second commit contains additional changes. In the original adoption of `NIOThrowingAsyncSequenceProducer` the code did not deal with backpressure being applied very well, in some cases causes hangs. A key bug was that it was not protected against re-entrant calls to `produceMore`. Such calls may happen e.g. when the producer has been asked to pause producing and then resume again before the initial read had completed. This resulted in overlapping reads and re-ordered data. This change introduces a new activity state which is protected by a lock and keeps track of if we are in the critical section to serialize access. `DirectoryEntryProducer` performs most of its logic within a lock and so doesn't seem to be impacted in the same way. ### Result: No functional changes. Internal changes reduce code duplication.
Motivation:
Adopt
NIOThrowingAsyncSequenceProducer
in NIOFileSystem to reduce code duplication.Modifications:
Adopt
NIOThrowingAsyncSequenceProducer
in NIOFileSystemDirectoryEntryProducer
andFileChunkProducer
Result:
No functional changes. Internal changes reduce code duplication.