Commit Graph
80 Commits
Author SHA1 Message Date
George Barnett 663ddc80f2 Dont hold lock over continuation in TokenBucket (#3455)
Motivation:

The various 'withMumbleContinuation' APIs are supposed to be invoked
synchronously with the caller. This assumption allows a lock to be
acquired before the call and released from the body of the
'withMumbleContinuation' after e.g. storing the continuation. However
this isn't the case and the job may be re-enqueued on the executor
meaning that this is pattern is vulnerable to deadlocks.

Modifications:

- Drop and reacquire the lock in TokenBucket.
- Switch to NIOLockedValueBox

Result:

Lower chance of deadlock
2025-12-01 15:46:46 +00:00
George Barnett cda536de37 Dont hold lock over continuation in NIOThrowingAsyncSequenceProducer (#3454)
Motivation:

The various 'withMumbleContinuation' APIs are supposed to be invoked
synchronously with the caller. This assumption allows a lock to be
acquired before the call and released from the body of the
'withMumbleContinuation' after e.g. storing the continuation. However
this isn't the case and the job may be re-enqueued on the executor
meaning that this is pattern is vulnerable to deadlocks.

Modifications:

- Drop and reacquire the lock in the NIOThrowingAsyncSequenceProducer.
- Merge 'next()' and 'next(for:)' methods in the state machine into a
single func; this reduces the amount of duplicated logic across the two
functions.

Result:

Lower chance of deadlock
2025-11-25 09:39:54 +00:00
George Barnett 5bf841dde5 Drop and reacquire lock over continuation call (#3452)
Motivation:

The various 'withMumbleContinuation' APIs are supposed to be invoked
synchronously with the caller. This assumption allows a lock to be
acquired before the call and released from the body of the
'withMumbleContinuation' after e.g. storing the continuation. However
this isn't the case and the job may be re-enqueued on the executor
meaning that this is pattern is vulnerable to deadlocks.

Modifications:

- Drop and reacquire the lock in the NIOAsyncWriter

Result:

Lower chance of deadlock
2025-11-24 11:13:50 +00:00
George BarnettandCory Benfield 664032bdd6 Wrap closures stored in the CallbackList (#3303)
Motivation:

The compiler is better at optimising closures wrapped in nominal types
than raw closures when used as generic parameters. CallbackList is used
a lot and stores an optional closure as well as on optional array of
closures. Wrapping these internally should save some allocations.

Modifications:

- Wrap the element stored in the `CallbackList`.

Result:

Fewer allocs

---------

Co-authored-by: Cory Benfield <lukasa@apple.com>
2025-07-14 16:48:26 +00:00
Cory Benfield 99ac8ec29c Add bpftrace allocations script (#3113)
Motivation:

When debugging allocations it is frequently helpful to be able to use
bpftrace instead of the more limited heaptrack.

Modifications:

Offer an equivalent of malloc-aggregation.d for bpftrace.

Result:

Allocation recording on Linux is available.
2025-07-11 11:58:05 +00:00
Rick Newton-Rogers adfd61adc5 Use Swift 6.0 docs pipeline (#2966)
### Motivation:

Documentation checking catches more issues in Swift 6.0.

### Modifications:

Adopt the Swift 6.0 image and fix the errors.

### Result:

More accurate docs.
2024-11-07 13:03:47 +00:00
Paul LeMarquand b812b1b731 Fix broken link to swift-server performance documentation (#2907) 2024-10-07 13:37:58 +00:00
Franz Busch f38b7fd38a Remove SPI from NIOAsyncChannel, new bootstrap methods, protocol negotiation and HTTP upgrade. (#2548)
# Motivation
Over the past months, we have been working on new async bridges to make using NIO's `Channel` from Swift Concurrency possible. Since this work was far reaching we have opted to land all of it as SPI. Now the time has come and we feel confident enough to make the SPI official API. This comes after testing the new APIs in various scenarios such as HTTP 1&2, HTTP upgrades, protocol negotiation and in benchmarks.

# Modification
This PR removes the SPI from the `NIOAsyncChannel`, the bootstrap methods, protocol negotiation and HTTP upgrade.

# Result
Everyone can use the our new APIs🚀
2023-10-17 14:14:02 +01:00
Franz Busch 0fb8cb7947 Add docs for the async NIO APIs (#2549) 2023-10-16 15:02:43 +01:00
George Barnett 417278754e Point docs to Swift Package Index (#2353)
Motivation:

The NIO docs are now published on the Swift Package Index but the README
still refers to GitHub pages.

Modifications:

- Update README and other docs to point to Swift Package Index.

Result:

Documentation links work
2023-01-23 06:09:43 -08:00
Fabian FettandCory Benfield c74c3bbabf [SelectableEventLoop] SR-15872; Save allocations when appending task (#2046)
* [SelectableEventLoop] SR-15872; Save allocations when appending task

* Add pr to workaround list

* Update alloc counters

* Update alloc script to include 5.6

* Update alloc counters

Co-authored-by: Cory Benfield <lukasa@apple.com>
2022-02-17 12:18:21 -08:00
Cory BenfieldandGeorge Barnett 06cb3dd096 Update workarounds list with our recent ones (#1962)
Co-authored-by: George Barnett <gbarnett@apple.com>
2021-09-27 09:48:39 +01:00
Tony Arnold d8348adc55 Minor rewording to clarify the location of the NIO1 to NIO2 migration guide (#1945) 2021-08-24 10:43:49 +01:00
Johannes WeissandCory Benfield 6e6465de31 docs: link to the SSWG's perf guide (#1882)
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>
2021-07-21 08:33:38 +01:00
Johannes Weiss 87c532383a remove NIO1 API shims (#1897)
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.
2021-07-13 12:36:28 +01:00
David Evans b0effbcfd9 Make Swift 5.2 the minimum requirement (#1860)
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.
2021-06-18 21:02:41 +01:00
Joakim HassilaandJohannes Weiss 8ea0afb4c4 Added second implementation of liburing as discussed in #1761. (#1804)
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>
2021-04-29 10:40:27 +01:00
Johannes Weiss a305518d88 implement CircularBuffer.first: to prevent allocs (#1814)
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.
2021-04-22 13:34:14 +01:00
Joakim Hassila 22b58cebee Update documentation related to allocation troubleshooting on Linux and the ability to run unit tests in parallel. (#1796)
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.
2021-04-09 11:49:48 +01:00
Johannes Weiss ea271eb1f5 docs: advanced performance analysis guide (#1738)
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.
2021-02-01 15:34:41 +00:00
Cory Benfield e7880565aa We use main as our development branch now. (#1651) 2020-09-24 18:02:44 +01:00
Peter Adams c5fa0b4565 Allocation diffing script no longer drops data. (#1513)
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.
2020-05-12 09:11:56 +01:00
George BarnettandJohannes Weiss ddb7109142 Include stackdiff-ing in the debugging-allocations doc (#1384)
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>
2020-02-06 16:10:04 +00:00
George Barnett b4483e5c49 Avoid curried thunks (workaround SR-12115) (#1374)
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.
2020-01-31 17:57:30 +00:00
Johannes WeissandCory Benfield 6bd0a9e61a document debugging with allocation tests (#1277)
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>
2019-12-02 11:05:04 +00:00
George Barnett 8aaaaab4fa Add an optimization tips document. (#1024)
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.
2019-06-05 07:48:57 -07:00
Johannes Weiss 39c6b87ff8 migration guide: Info about B2MD (#949)
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
2019-04-05 17:22:44 +01:00
Johannes Weiss 09bace11d6 minor fixes in docs (#928)
Motivation:

Some things weren't 100% clear or wrong, let's fix em.

Modifications:

fixed 'em.

Result:

better docs
2019-03-26 11:26:10 +00:00
Johannes Weiss b8368b6e09 update the documentation for NIO 2 release (#927)
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.
2019-03-26 09:11:28 +00:00
Johannes Weiss df0b0594ec CircBuffer: docs: add that indices are no longer Strideable (#914)
Motivation:

CircularBuffer indices are no longer `Strideable`, document this.

Modifications:

added to the public api changes doc

Result:

better docs
2019-03-23 15:05:12 +00:00
Johannes Weiss a8fbcf080b EmbeddedChannel: remove mystery bools (#917)
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
2019-03-22 12:34:16 +00:00
Johannes Weiss 4ffa858ce6 make HTTPMethod.hasRequestBody internal (#908)
* 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
2019-03-19 13:02:34 +00:00
Cory Benfield 8adf87baa6 Update migration guide with now-converging repos. (#905)
Motivation:

swift-nio-http2 and swift-nio-transport-services are now converging.

Modifications:

Updated the migration guide.

Result:

Docs will be up to date.
2019-03-15 15:03:01 +00:00
Johannes Weiss 08ae2308be migration guide: swift-nio-ssl has converged (#901)
Motivation:

We should have accurate information in our guides.

Modifications:

Note that swift-nio-ssl has converged.

Result:

correct info
2019-03-13 17:02:04 +00:00
Johannes Weiss 785f7620f2 fix wrong URL for swift-nio-extras 2019-03-08 19:30:39 +00:00
Johannes Weiss edda576522 update migration guide: convergence (#891)
Motivation:

Mention convergence in migration guide.

Modifications:

tell people about the correct dependencies in the migration guide.

Result:

happier users.
2019-03-08 19:30:02 +00:00
Johannes Weiss 36a52e1ea3 remove WebSocketFrameDecoder inline error handling (#885)
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
2019-03-08 19:11:39 +00:00
Johannes Weiss acb37911c0 remove overloading from scheduleRepeatedTask (#886)
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
2019-03-08 15:37:58 +00:00
Johannes Weiss 22e6cd3c67 HTTP/1 headers simplification & cleanup (#857)
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
2019-03-06 18:11:40 +00:00
Johannes Weiss eb524c72ad improve and simplify MessageToByteEncoder (#868)
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
2019-03-04 19:19:53 +00:00
Johannes Weiss 7528ecd374 convert NIOWebSocketUpgradeError from enum to struct (#866)
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
2019-03-04 14:19:18 +00:00
Johannes Weiss baa3390b15 remove HTTPResponseCompressor (#865)
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
2019-03-04 13:52:30 +00:00
Cory Benfield 9c07f89ec7 Allow delaying HTTP upgrade decisions. (#844)
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.
2019-03-01 18:24:59 +00:00
Johannes Weiss da52b59ced fix/improve some NIO1APIShims (#856)
Motivation:

We had wrong/suboptimal API shims.

Modifications:

improve them

Result:

easier porting from NIO1 to NIO2
2019-02-28 16:16:17 +00:00
Johannes Weiss 37a64b74c6 NIO 1 to 2 migration guide (#847)
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
2019-02-28 11:21:48 +00:00
Johannes Weiss 14327af193 don't leak pthread_keys (#157)
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.
2019-02-26 14:57:47 +00:00
Johannes Weiss a41280919e rename ctx to context (#842)
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
2019-02-25 18:20:22 +00:00
Johannes Weiss 862533d089 B2MD: Don't deliver data after error (#837)
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
2019-02-25 17:18:11 +00:00
Johannes Weiss afbab95f27 address #186: rename BlockingIOThreadPool to NIOThreadPool (#838)
Motivation:

The thread pool implementation can be used for many things not just
blocking IO.

Modifications:

rename BlockingIOThreadPool to NIOThreadPool

Result:

fixes #186
2019-02-25 16:51:47 +00:00
Johannes Weiss ff31b3135d improve B2MD EOF handling (#831)
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
2019-02-21 14:14:50 +00:00