Commit Graph

161 Commits

Author SHA1 Message Date
George Barnett 4dfae01cc6
Add a pooled recv buffer allocator (#2362)
Motivation:

Channels can read `ChannelOptions.maxMessagesPerRead` times from a
socket in each read cycle. They typically re-use the same buffer for
each read and rely on it CoWing if necessary. If we read more than once
in a cycle then we may CoW the buffer. Instead of reusing one buffer we
can reuse a pool of buffers limited by `maxMessagesPerRead` and cycle
through each, reducing the chance of CoWing the buffers.

Modifications:

- Extend `RecvByteBufferAllocator` to provide the size of the next
  buffer with a default implementation returning `nil`.
- Add an recv buffer pool which lazily grows up to a fixed size and
  attempts to reuse buffers where possible if doing so avoids CoWing.

Results:

Fewer allocations
2023-02-20 17:00:19 +00:00
David Nadoba 3d18e94683
Add Swift 5.8 CI and update nightly CI to Ubuntu 22.04 (#2350)
* Add Swift 5.8 CI

* Update nightly CI to Ubuntu 22.04

* Allow slight allocation variance in `1000_udpconnections` test
2023-01-18 10:17:12 +00:00
Philip Brown 59e1f6f375
Tail allocate mutex and a generic value using ManagedBuffer (#2349)
Motivation:

Currently, NIOLock and NIOLockedValueBox incur unnecessary allocation and indirection costs.

Modifications:

Create namespace LockOperations for organization
Create LockStorage<Value>, a subclass of ManagedBuffer<LockPrimitive, Value>
Store the mutex as the header and the generic value as the first and only element
Update NIOLock and NIOLockedValueBox to use LockStorage

Result:

Optimal lock and value memory layout
Fewer allocations and less indirection
Code generation is excellent
2023-01-17 16:11:10 +00:00
David Nadoba 1ce136b4c3
Fix main nightly CI (#2337)
* Fix nightly CI

* conditionalization of signal for architecture
2023-01-09 18:34:48 +00:00
Cory Benfield 0760383b38
Measure allocations applying WS mask (#2333)
Motivation:

We're missing some alloc tests on the WS mask.

Modifications:

- Add extra alloc tests for the WS mask

Result:

We'll have more tests
2022-12-13 18:05:27 +00:00
Franz Busch 1abe64c5e6
Add benchmarks for `NIOAsyncWriter` and `NIOAsyncSequenceProducer` (#2301)
# Motivation
We landed the async bridge types a while back but never added allocation and performance tests. Since we expect these types to be used performance critical paths we really should cover those with tests.

# Modification
Extends the allocation counter scaffolding to support async tests. Furthermore, add allocations tests for both the writer and producer. Lastly, I a also added a performance test for the producer.

# Result
We now have baseline tests for the `NIOAsyncWriter` and `NIOAsyncSequenceProducer`

Co-authored-by: Cory Benfield <lukasa@apple.com>
2022-10-26 03:51:20 -07:00
George Barnett fcca969463
Raise minimum supported Swift version from 5.4 to 5.5 (#2267)
Motivation:

SwiftNIO periodically drops support for older Swift versions. Now that
5.7 has been released, 5.4 will be dropped.

Modifications:

- Remove 5.4 specific Package.swift and docker-compose
- Update the 5.7 docker-compose to use the released 5.7 and move from
  focal (2004) to jammy (2204)
- Remove unused swiftformat from Dockerfile
- Update tools version in syscall wrapper tests to 5.5
- Update docs

Results:

Minimum Swift version is 5.5
2022-09-29 11:47:44 +01:00
George Barnett 39e61f636f
Update allocation limits (#2272)
Motivation:

a16e2f54a2 allocates more in some cases
because of an additional channel handler.

Modifications:

- Update alloc limits

Result:

CI passes.
2022-09-29 10:10:16 +01:00
Cory Benfield 6918034260
Update HTTP parser to LLHTTP (#2263)
Motivation:

The node.js HTTP parser library that we use has been unmaintained for some time. We should move to the maintained replacement, which is llhttp. This patch will update our dependency and bring us over to the new library, as well as make any changes we need.

Modifications:

This patch comes in 4 parts, each contained in a separate commit in the PR.

The first commit drops the existing http_parser code and updates some of the repo state for using llhttp.
The second commit rewrites the update script to bring in llhttp instead of http_parser.
The third runs the actual script. You can skip reviewing this except to sanity check the outcome.
The fourth commit updates the NIO code and the tests to get everything working.

In general the substance of the product modifications was minimal. The logic around keeping track of where we are in the buffer and how upgrades work has changed a bit, so that required some fiddling. I also had to add an error reporting path for the delegates to be able to throw specific errors that llhttp no longer checks for. Finally, I removed two tests that were a little overzealous and that llhttp does not police.

Result:

Back on the supported path.
2022-09-13 14:09:57 +01:00
Cory Benfield 901e9692b9
Validate missing imports in CI (#2245) 2022-08-15 10:26:34 -07:00
Cory Benfield f5448fbbc2
Provide NIOAsyncTestingChannel (#2238)
Motivation

Testing versions of NIO code that involve interfacing with Swift
Concurrency is currently a difficult business. In particular,
EmbeddedChannel is not available in Swift concurrency, making it
difficult to write tests where you fully control the I/O.

To that end, we should provide a variation of EmbeddedChannel that makes
testing these things possible.

Modifications

Provide an implementation of NIOAsyncTestingChannel.

Results

Users can write tests confidently with async/await.
2022-08-10 11:09:56 +01:00
tomer doron 712e207f26
initial adoption of DocC based documentaiton (#2235)
* initial adoption of DocC based documentaiton

motivation: use DocC for docs

change:
* add DocC catalog to NIO target, as the "landing page"
* remove jazzy doc generation script
* add Package.swift with tools-version 5.6 so that DocC can be used, and add a dependency on the DocC plugin
* udpate soundness script

* * add packge.swift files for older vrsions
* adjust waning-as-error and enable-test-discovery to the different permutations

* fixup

* remove jazzy

Co-authored-by: Cory Benfield <lukasa@apple.com>
2022-08-08 03:55:18 -07:00
Cory Benfield 7fbaed6f4a
Use correct alloc limits for 5.7 (#2193) 2022-06-14 11:57:26 +01:00
Cory Benfield ec4072c925
Use 5.7 nightlies (#2186) 2022-06-13 03:06:35 -07:00
David Nadoba 0e2818bf86
Remove `@preconcurrency` from internal `EventLoopFuture` methods (#2135)
* add @preconcurrency again as it otherwise results in one more allcation in 1000_udpconnections
2022-06-07 07:09:44 -07:00
David Nadoba 391ab9122c
Reduce the alloc limits for main (#2118)
The nightly builds have improved, so the alloc limits can drop slightly
2022-05-16 09:56:45 -07:00
David Nadoba 14ffe73e1b
Reduce the alloc limits of `1000_tcpconnections` for main (#2116)
The nightly builds have improved, so the alloc limits can drop slightly
2022-05-16 02:48:31 -07:00
Cory Benfield b1b44ca67b
Reduce the alloc limits for main (#2095)
The nightly builds have improved, so the alloc limits can drop slightly
2022-05-04 15:49:40 +01:00
Fabian Fett dc8a317a24
Drop support for Swift 5.2 and 5.3 (#2080)
* Drop support for 5.2 and 5.3

As outlined in a [Swift forums post in November ’21](https://forums.swift.org/t/swiftnio-swift-version-support/53232), SwiftNIO will only support the latest non-patch Swift release and the 2 immediately prior non-patch versions.

In this commit we drop support for Swift 5.2 and 5.3. We update CI for Swift 5.4 to run on bionic instead of focal to ensure that we still test bionic.

* Added Versions paragraph to Security document

* Apply suggestions from code review

Co-authored-by: Cory Benfield <lukasa@apple.com>

Co-authored-by: Cory Benfield <lukasa@apple.com>
2022-04-20 11:48:41 +01:00
Cory Benfield dde891c624
Update alloc limits for nightly. (#2071)
We regressed allocs in nightly, probably for a Swift bug. Fixing it is
tracked in #2070, for now we're going to raise the limits so CI isn't
moaning all the time.
2022-03-23 10:05:11 -07:00
tomer doron aa631d3c8c
ci update (#2066)
motivation: 5.6 is out

changes:
* use release version of 5.6
* add docker setup for 5.7 (using nightly for now)
2022-03-16 21:28:58 -07:00
Cory Benfield af161d59f5
Add limits for the new test (#2060) 2022-03-08 09:22:15 +00:00
Fabian Fett 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
Fabian Fett c562f962b8
Add an allocation test for execute which needs to hop threads. (#2047)
* Add an allocation test for execute which needs to hop threads.

* Add new alloc limits for CI
2022-02-17 09:21:40 +00:00
Cory Benfield 398378653f
Add 5.6 nightly CI (#2032)
The 5.6 nightly images are available, let's use them.
2022-01-18 09:35:51 +00:00
Franz Busch 3c3e5fc80b
Call the `cancellationTask` of `Scheduled` directly (#2011)
### Motivation:

In my previous PR https://github.com/apple/swift-nio/pull/2010, I was able to decrease the allocations for both `scheduleTask` and `execute` by 1 already. Gladly, there are no more allocations left to remove from `execute` now; however, `scheduleTask` still provides a couple of allocations that we can try to get rid of.

### Modifications:

This PR removes two allocations inside `Scheduled` where we were using the passed in `EventLoopPromise` to call the `cancellationTask` once the `EventLoopFuture` of the promise fails. This requires two allocations inside `whenFailure` and inside `_whenComplete`. However, since we are passing the `cancellationTask` to `Scheduled` anyhow and `Scheduled` is also the one that is failing the promise from the `cancel()` method. We can just go ahead and store the `cancellationTask` inside `Scheduled` and call it from the `cancel()` method directly instead of going through the future.

Importantly, here is that the `cancellationTask` is not allowed to retain the `ScheduledTask.task` otherwise we would change the semantics and retain the `ScheduledTask.task` longer than necessary. My previous PR https://github.com/apple/swift-nio/pull/2010, already implemented the work to get rid of the retain from the `cancellationTask` closure. So we are good to go ahead and store the `cancellationTask` inside `Scheduled` now

### Result:

`scheduleTask` requires two fewer allocations
2021-12-15 13:46:53 +01:00
Franz Busch f228e264fc
Convert ScheduledTask to a struct (#2010)
### Motivation:

In my previous PR https://github.com/apple/swift-nio/pull/2009, I added baseline performance and allocation tests around `scheduleTask` and `execute`. After analysing, the various allocations that happen when scheduling a task there were only a few that could be optimized away potentially.

### Modifications:

This PR converts the `ScheduledTask` class to a struct which will reduce the number of allocations for scheduling tasks by 1. The only thing that needs to be worked around when converting to a struct is giving it an identity so that we can implement `Equatable` conformance properly. I explored two options. First, using an `ObjectIdentifier` passed to the init. Second, using an atomic counter per EventLoop. I went with the latter since the former requires an additional allocation in the case of calling `execute`

### Result:

`scheduleTask` and `execute` require one less allocation
2021-12-14 17:40:40 +00:00
Franz Busch 213eb6887e
Add baseline performance and allocation tests for scheduling tasks and executing (#2009)
### Motivation:

In issue https://github.com/apple/swift-nio/issues/1316, we see a large number of allocations to happen when scheduling tasks. This can definitely be optimized. This PR adds a number of baseline allocation and performance tests for both `scheduleTask` and `execute`. In the next PRs, I am going to try a few optimizations to reduce the number of allocations.

### Modifications:

Added baseline performance and allocation tests for `scheduleTask` and `execute`
2021-12-13 16:33:13 +00:00
Cory Benfield 9d033fd6ed
Migrate to Swift 5.5 release in CI. (#1967) 2021-09-22 09:23:09 +01:00
Cory Benfield 19403414ba
Get unit tests running again on nightly builds. (#1961)
Motivation:

In February, @weissi noticed that the nightly builds of Swift could no
longer compile the unit tests. We disabled them at that time and
reported an upstream bug, https://bugs.swift.org/browse/SR-14268. This
is not an ideal situation, but the Swift core team has provided a
workaround we can use to re-enable the tests.

Modifications:

Provide free functions that wrap some specific extension methods that
are called in unit tests, and amend the call sites to use them.

Result:

We can re-enable the nightly tests.
2021-09-17 20:50:29 +01:00
Cory Benfield fb48bdd827
Work around Xcode 13 GM SDK issues. (#1956)
Motivation:

Xcode 13 GM shipped with a Swift overlay for libsystem in macOS that
marked free's first argument as non-nullable. This leads to an awkward
breakage for us, because we're trying to hold a reference to free as a
function pointer, and to do that we had an explicit type annotation.

We'd like to keep NIO compiling in Xcode 13 GM.

Modifications:

- Defined the free function as a thunk that passes through to the
  underlying OS free call, but takes its first argument as non-nullable.

Result:

Should compile on the Xcode 13 GM again.
2021-09-16 08:34:18 +01:00
George Barnett 7e1ca33bc9
Add performance and allocation tests for canonical form headers (#1953)
Motivation:

To justify performance changes we need to measure the code being
changed. We believe that `HTTPHeaders.subscript(canonicalForm:)` is a
little slow.

Modifications:

- Add allocation and performance tests for fetching header values in
  their canonical form

Results:

More benchmarks!
2021-09-13 16:28:07 +01:00
George Barnett 2f189a39f6
Fix doc generation and jazzy version (#1950)
* Fix doc generation and jazzy version

From: https://github.com/apple/swift-nio-extras/pull/141

motivation: fix ci

changes:
* only install ruby and jazzy on focal since jazzy id not supported onlder versions of ubuntu
* fix doc generations script adjusting it to latest source-kittent syntax

* Always install ruby: we need it for generating a test manifest
2021-09-02 18:08:04 +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
Johannes Weiss b23f40b4fa
add Swift 5.5 job (#1845) 2021-06-01 18:58:56 +01:00
Cory Benfield 43fa7686db
Add alloc counter benchmark for result erasing maps. (#1858)
Motivation:

Peter thinks that result-erasing maps should not allocate, and we have
special code paths in the code to try to make Void -> Void maps not
allocate. Sadly, both code paths currently do allocate.

Per our rules for not trying to make optimizations without data, we
should start measuing these closures so we can make optimizations.

Modifications:

- Added an alloc couter test for result-erasing maps.

Result:

Alloc counter test suitable for any fix of #1697.
2021-05-25 12:56:38 +01:00
tomer doron aa9cfb6fb6
fix 5.4. docker setup (#1851)
motivation: update syntax for release images

changes: replace use of "base_image" with "ubuntu_version" and "swift_version" pair, which the intended way to use release images
2021-05-07 08:30:27 +01:00
Johannes Weiss b27b08a828
docker: use 5.4 release instead of nightly (#1843) 2021-05-04 16:21:44 +01:00
Cory Benfield 8369411d6f
Stop measuring alloc counts on 5.0 (#1826)
Motivation:

5.0 is several years old now, and while we still support it there is
beginning to be some conflict with performance optimizations for newer
Swift versions. We should stop counting the allocation counts on this
version now: we no longer care as much about regressions.

Modifications:

- Stop setting alloc counter limits on 5.0
- Remove the script that tries to add them back.

Result:

No longer measure allocs on 5.0
2021-04-28 14:02:13 +01:00
Johannes Weiss 0a860b1c3d
CI: print out version info (#1821)
Motivation:

Sometimes it's useful to know the kernel & Swift versions that CI uses.

Modifications:

Print the versions in the soundness check.

Result:

More info.

Co-authored-by: Cory Benfield <lukasa@apple.com>
2021-04-27 13:34:54 +01:00
Fabian Fett e08f9f903e
Reducing allocations in future chains (#1818) 2021-04-26 13:54:26 +01:00
Fabian Fett 72f5a56328
Less allocs during `flatMapErrorThrowing` (#1816)
Motivation:

We alloc quite a lot with our implementations of flatMapThrowing and flatMapErrorThrowing.
While we don't use Futures a lot in NIO itself a lot of our users, depend quite a bit on them. Let's make their code faster.

Modifications:

Create a Promise and use _whenComplete directly instead of going through another flatMap method

Result:

In my testing I see a reduction of 3 allocs per invocation 🎉
2021-04-23 19:27:38 +01:00
Johannes Weiss 06ce11fb82
generic integer bit packing (#1807)
Motivation:

With the registration ID refactoring (#1801) we'll now have the third
reimplementation of integer bit packing. Three is one too many, let's
make it generic.

Modifications:

Introduce generic integer bit packing and use it for _UInt56/24.

Result:

- Less bit packing code.
- Will simplify #1801
2021-04-22 15:02:47 +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
Johannes Weiss ce4328689c
disable tests on main (#1790)
Motivation:

The Swift compiler can still not compile NIO's tests on main, so I'm
proposing this sad workaround for
https://bugs.swift.org/browse/SR-14268 .

Modifications:

Don't compile (or run) tests on `main` :(

Result:

May get a green tick.
2021-03-30 16:05:07 +01:00
Johannes Weiss 2d27890eb8
normalise alloc counter slack (#1789)
Motivation:

Usually, we add a more or less random number of slack allocations to
make sure the tests don't spuriously fail. This makes it quite costly to
support new Swift versions.

Modifications:

Add a script which can spit you out the right allocation limits
including slack.

Result:

Easier to support new Swift versions
2021-03-30 14:42:33 +01:00
Johannes Weiss 589a16e70b
docker setup for main nightlies (#1752)
Co-authored-by: Cory Benfield <lukasa@apple.com>
2021-03-23 13:01:14 +00:00
Cory Benfield 6c18d23930
Make ChannelHandler removal cheaper. (#1784)
Motivation:

Any version of ChannelHandler removal that does not have a
ChannelHandlerContext already in hand is currently excessively
expensive. This is because it allocates a promise and a callback for
finding the context, despite already having a promise in hand for users
to complete.

We can remove a pair of allocations here by jumping to the event loop
directly and then running our operations synchronously.

Modifications:

- Rewrite removeHandler(name:promise:) and removeHandler(_:promise:) to
  jump directly to the event loops and then work synchronously.

Result:

Cheaper code
2021-03-18 15:43:21 +00:00
Cory Benfield c3479df8b7
Add allocation counter tests handler add/remove (#1785)
Motivation:

Allocation counter tests are good, and we aren't measuring this today.

Modifications:

- Wrote some add/remove tests that use different remove functions.

Result:

Better insight into performance.
2021-03-18 14:42:51 +00:00
George Barnett e2b39de23b
Add synchronous helpers for HTTP1 pipeline setup (#1762)
Motivation:

We recently added a synchronous view of the `ChannelPipline` so that
callers can avoid allocating futures when they know they're on the right
event loop. We also offer convenience APIs to configure the pipeline for
particular use cases, like an HTTP/1 server but we don't have
synchronous versions of these APIs yet. We should have parity
between as synchronous and asyncronous APIs where feasible.

Modifications:

- Add synchronous helpers to configure HTTP1 client and server pipelines

Result:

Callers to synchronously configure HTTP1 client and server pipelines.
2021-03-04 12:04:26 +00:00