Motivation:
Instead of reproducing partial information, it makes more sense to link to the SSWG's guide which is more complete.
Modification:
Remove incomplete information and swap for a link.
Result:
Better docs.
Co-authored-by: Cory Benfield <lukasa@apple.com>
Motivation:
The lastest NIO versions require Swift 5.2+ to compile. Given that
hopefully nobody ever created a NIO1 application for Swift 5.2+, I'd say
it's about time to remove the NIO1 API shims (and related docs).
Modification:
- remove the NIO1 API shims
- remove the migration docs
Result:
Less code.
Make Swift 5.2 the minimum requirement, dropping support for Swift 5.0 and 5.1.
Motivation:
Whenever we have problems, Swift 5.0 and 5.1 seem to be the culprits. Dropping support for these very old versions will require less maintenance and free up our time to work on new features.
Modifications:
Set the tools version in Package.swift to 5.2
Remove CI configurations for 5.0 and 5.1
Update the various readmes to reflect that this change will be rolled out in NIO 2.30.0
Result:
Swift 5.2 is the minimum version of Swift required to use NIO.
Motivation:
As outlined in #1761, io_uring is a new async I/O facility on Linux.
This commit includes a second stab at adding this to SwiftNIO.
Modifications:
Added Uring Selector implementation.
Added liburing support shims.
Disabled one assert that trips during normal usage likely due to async nature of poll updates, for discussion
Added shared kernel sqpoll ring support (can be run with normal user privs in 5.13)
Support for both single shot polls (should work all the way back to 5.1 kernels, needs testing) and multishot streaming polls and modifications for polls (scheduled due in 5.13) for slightly better performance (and better impedance match to SwiftNIO usage)
Added extensive debug logs which can be enabled with -D compiler flags (should likely be removed when bringup and testing is complete)
Adjusted tests.
Added documentation.
Result:
Basic liburing support is in place.
Co-authored-by: Johannes Weiss <johannesweiss@apple.com>
Motivation:
Due to https://bugs.swift.org/browse/SR-14516 , we sometimes get
allocating (!?) `subscript.read` accessors in the CircularBuffer.first
depending on the `Element` type...
Modifications:
Implement `CircularBuffer.first` instead of inheriting it from
Collection.
Result:
Fewer allocs in some cases.
Motivation:
It's not obvious how to do analysis of allocation regressions on Linux, so some documentation would be helpful.
The run time for the unit tests can be quite long (a couple of minutes), can be cut down significantly if running tests in parallel, adding a hint about that.
Modification:
Updated documentation.
Result:
Easier to troubleshoot mallocs on Linux and faster running of unit tests.
Motivation:
Sometimes, advances performance analysis is required and we didn't have
documents describing this.
Modifications:
Add a document describing advanced performance analysis with `perf`.
Result:
More guides.
Allocation diffing script no longer drops data.
Motivation:
Looking at allocations is hard enough without the script getting the allocation counts wrong.
Modifications:
Where multiple allocations resolved to the same "key" only the last allocation was accounted for. I have changed the script to store all allocations - still keyed in the same way. When diffing the total number of allocations is used - if they are different the total and all contributing stack traces are output.
Added a total for all allocations everywhere at the end together with a difference number.
Output all stack traces before and after contributing to a detected diff.
Update the documentation to reflect changes.
Change the threshold for reporting diffs from > 1000 to >= 1000. This means if allocations go from 1000 to 2000 they are reported as a difference rather than a new allocation.
Result:
It is now easier - if somewhat more verbose to compare allocations.
Motivation:
We recently grew a script to diff the output of `malloc-aggregation.d`,
we should document how this can be used when debugging allocation
regressions.
Modifications:
- Update the doc to include an example of using the script to debug an
allocation regression
- Fix a bug in the script where before/after were mixed up
- Fix a bug in the script where usage would print '()\n' instead of '\n'
Result:
- Better info on debugging allocations
Co-authored-by: Johannes Weiss <johannesweiss@apple.com>
Motivation:
Calling `function(otherFunction)` allocates, but
`function({ otherFunction($0) }` does not.
See: SR-12115 and SR-12116.
Modifications:
Avoid passing functions directly; pass them in new closures instead.
Result:
Fewer allocations.
Motivation:
The tooling around the allocation counter tests is pretty opaque and
also not easy to use.
Modifications:
Document what interested folks should know.
Result:
More people will be able to debug allocations in SwiftNIO.
Co-Authored-By: Cory Benfield <lukasa@apple.com>
Motivation:
NIO doesn't offer any tips of on how to write performant code. After
discussing with @weissi we decided it would be useful to gather and
document some useful tips and tricks.
Modifications:
Started an optimization tips document.
Result:
Easier for NIO users to write performant code.
Motivation:
@tomerd learned the hard way that there were some subtle changes in
B2MDs around intercepting arbitrary channel events. Previously,
intercepting those was illegal but possible. In NIO 2, it's impossible.
Modifications:
add a description for what changed
Result:
easier migrations
Motivation:
A bunch of things change with the release of NIO 2. We should update the
documentation to reflect that.
Modifications:
- update readme
- update migration guide
Result:
up to date docs.
Motivation:
EmbeddedChannel.finish/writeInbound/writeOutbound returned some mystery
bools. I always had to check the code to remember what they actually
meaned.
Whilst this is technically a breaking change, I couldn't find any users
of the return values on Github that are using the convergence releases.
Modifications:
Replace them by enums giving you all the information.
Result:
- fixes#916
- clearer APIs
* make HTTPMethod.hasRequestBody internal
Motivation:
HTTPMethod.hasRequestBody was unnecessarily public.
Modifications:
make it internal
Result:
fixes#151
* Update public-api-changes-NIO1-to-NIO2.md
Motivation:
swift-nio-http2 and swift-nio-transport-services are now converging.
Modifications:
Updated the migration guide.
Result:
Docs will be up to date.
Motivation:
Mention convergence in migration guide.
Modifications:
tell people about the correct dependencies in the migration guide.
Result:
happier users.
Motivation:
Follows on from the work done in #528 for #527: we have moved the the
default error handling out of WebSocketFrameDecoder, but had to leave
the code there for backward compatibility reasons. We can remove that
code now.
Modifications:
Removed automatic error handling code in WebSocketFrameDecoder.
Result:
- fixes#534
Motivation:
scheduleRepeatedTask had two overloads: for synchronous and asynchronous
tasks. They however had the same name so they were pretty much
impossible to use.
Modifications:
rename the asynchronous version of scheduleRepeatedTask to
scheduleRepeatedAsyncTask
Result:
- NIO easier to use
- fixes#882
Motivation:
The HTTP/1 headers were quite complicated, CoW-boxed and exposed their
guts (being a ByteBuffer). In Swift 5 this is no longer necessary
because of native UTF-8 Strings.
Modifications:
- make headers simply `[(String, String)]`
- remove `HTTPHeaderIndex`, `HTTPListHeaderIterator`, etc
Result:
- simpler and more performant code
Motivation:
MessageToByteEncoder was a protocol that similar to ByteToMessageDecoder
was pretty hard to hold correctly (override some methods but not
others). This PR brings MessageToByteEncoder more in line with the new
ByteToMessageDecoder.
Modifications:
- refactor `MessageToByteEncoder`
- introduce `MessageToByteHandler`, similar to `ByteToMessageHandler`
Result:
- better API, more similar to ByteToMessageDecoder
- fixes#864
Motivation:
We need to fix#577 sometime soon and in preparation of that we'll
change convert NIOWebSocketUpgradeError from enum to struct.
Modifications:
convert NIOWebSocketUpgradeError from enum to struct
Result:
- NIOWebSocketUpgradeError can be adjusted without SemVer major breaking
changes
- fixes#839
Motivation:
We're not happy with HTTPResponseCompressor's API and it needs to
incubate a little more, hence moving to
[`swift-nio-extras`](https://github.com/apple/swift-nio-extras).
Modifications:
- removed HTTPResponseDecoder
- removed the zlib dependency
Result:
- no more HTTPResponseDecoder
Motivation:
While the HTTPServerUpgrader and WebSocketUpgrader allowed users to take
their time when reconfiguring the pipeline after they decided to upgrade,
users had to synchronously decide if they wanted to upgrade. This is a bit
inconvenient.
A particular limitation here is that some routes may want to upgrade
only if the upgrading user is authenticated. Checking authentication
credentials is almost always an I/O operation, and so cannot safely be done
on the event loop. Our original design made this impossible.
Modifications:
- Changed the shouldUpgrade callback to return a Future.
- Passed the shouldUpgrade callback the Channel that is upgrading, in
no small part so that it has an EventLoop it can create Futures
on.
- Rewrote the upgrader to handle this new state.
Result:
Users can delay decisions about when to upgrade.
Motivation:
The NIO 1 to 2 migration is not too bad if you know a few tricks. So we
should list them in a migration guide.
Modifications:
add first cut of migration guide
Result:
happier users
Motivation:
Previously we leaked `pthread_key`s as we only ever called
`pthread_key_create` but never `pthread_key_delete`. This patch fixes
that.
Modifications:
- made `ThreadSpecificVariable` a class (so we get lifecycle management
through ARC)
- instead of just storing the value, store `Box<(ThreadSpecificVariable<T>, T)>`
so we can control the lifecycle of the `ThreadSpecificVariable` as
needed
Result:
We don't leak `pthread_key`s anymore.
Motivation:
`ctx` was always an abbreviation was 'context` and in Swift we don't
really use abbreviations, so let's fix it.
Modifications:
- rename all instances of `ctx` to `context`
Result:
- fixes#483
Motivation:
B2MD should never call any of the decode functions after the user has
thrown an error.
Modifications:
introduce an error state and make sure we don't call out if in error
state
Result:
B2MD more correct
Motivation:
The thread pool implementation can be used for many things not just
blocking IO.
Modifications:
rename BlockingIOThreadPool to NIOThreadPool
Result:
fixes#186
Motivation:
Previously B2MDs didn't really have defined semantics regarding EOFs and
we didn't tell them if there was an EOF. Also `decodeLast` was optional
and all that was bad.
Modifications:
- require `decodeLast`
- add a `seenEOF: Bool` parameter to `decodeLast` which tells the
decoder if an EOF has been seen
Result:
- clearer semantics
- more information
Motivation:
- `ChannelPipeline.add(name:handler:...)` had a strange order of arguments
- `remove(handler:)` and `remove(ctx:)` both remove `ChannelHandler`s
but they read like they remove different things
So let's just fix the argument order and name them `addHandler` and
`removeHandler` making clear what they do.
Modifications:
- rename all `ChannelPipeline.add(name:handler:...)`s to `ChannelPipeline.addHandler(_:name:...)`
- rename all `ChannelPipeline.remove(...)`s to `ChannelPipeline.removeHandler(...)`
Result:
more readable and consistent code
Motivation:
Opaque indices are a good idea for collections, (Marked)CircularBuffer
should use those too.
Modifications:
Cheapest possible implementation for opaque indices, could be much
improved. This is the cheapest possible implementation for opaque
indices and this could be much improved later, see #682 but the
improvements won't be SemVer major :).
Result:
first stab at #682
Motivation:
ChannelOptions used a too complicated mechanism for what they are.
Modifications:
- change the ChannelOptions to a much simpler mechanism
- rename the generic parameters from T to Option
Result:
code easier to read and understand
Motivation:
Collisions with Foundation and other standard libraries is painful.
Modifications:
- rename `FileHandle` to `NIOFileHandle`
- rename `Thread` to `NIOThread` (only exposed in docs)
Result:
fewer collisions
Motivation:
ChannelOptions should've always been Equatable and so far we've hacked
around them not being Equatable when we wanted to compare them.
Modifications:
make all ChannelOptions Equtable
Result:
- ChannelOption comparison actually works
- fixes#598
- make more ChannelOptions stuff inlinable to not regress allocations
Motivation:
As part of NIO2 - much work has been done to round out the API of EventLoopFuture. This finishes existing public API parameters to be more in line with Swift API guidelines.
Modifications:
Methods in EventLoopFuture that had `eventLoop` as a parameter label have been changed to `on`
Results:
EventLoopFuture public API is more "Swifty" with calls such as `future.hop(to: eventLoop)` rather than `future.hopTo(eventLoop: eventLoop)`
Motivation:
ByteBuffer methods like `set(string:)` never felt very Swift-like and
also didn't look the same as their counterparts like `getString(...)`.
Modifications:
- rename all `ByteBuffer.set/write(<type>:,...)` methods to
`ByteBuffer.set/write<Type>(...)`
- polyfill the old spellings in `_NIO1APIShims`
Result:
code more Swift-like
Motivation:
If ChannelHandler removal worked correctly, it was often either by
accident or by intricate knowledge about the implementation of the
ChannelHandler that is to be removed. Especially when it comes to
re-entrancy it mostly didn't work correctly.
Modifications:
- introduce a `RemovableChannelHandler` API
- raise allocation limit per HTTP connection by 1
(https://bugs.swift.org/browse/SR-9905)
Result:
Make things work by contruction rather than accident
Motiviation:
After adding `ELF.whenAllComplete` the concept of "fail fast" and "fail slow" for reducing an array of future results together was introduced.
This commit adds that concepts with the `andAll* methods that act as simple completion notifications.
Modifications:
Rename `EventLoopFuture.andAll(_:eventLoop:)` to `andAllSucceed(_🔛)` to denote its "fail fast" nature, and to match Swift API guidelines.
Add new `EventLoopFuture.andAllComplete(_🔛)` for a "fail slow" companion.
Shift implementation of `whenAllComplete(_🔛)` to be usable without unnecessary allocations in `andAllComplete`
Result:
EventLoopFuture now has two methods for "flattening" arrays of EventLoopFuture into a single notification ELF
Motivation:
The `ELF.cascade` methods have a parameter label `promise` that does not match Swift API Guidelines, and a way to cascade just successes is not available - while for failures there is.
Modifications:
`ELF.cascade*` methods that already exist have had their `promise` label renamed to `to`, and a new `ELF.cascadeSuccess` method has been added.
Result:
EventLoopFuture now has the cascade methods `ELF.cascade(to:)`, `ELF.cascadeFailure(to:)`, and `ELF.cascadeSuccess(to:)`
Motivation:
initialRingCapacity is not a great name, initialCapacity is much better
Modifications:
rename CircularBuffer(initialRingCapacity:) to initialCapacity
Result:
more consistent code