Commit Graph

129 Commits

Author SHA1 Message Date
Cory Benfield fd35cd9e52
Extend the integration test harness to track FDs (#2411)
* Extend the integration test harness to track FDs

Motivation

This patch extends the NIO integration test harness to track
file descriptors, in particular to search for leaks. This
change has been validated on Linux and Darwin, and in both cases
correctly diagnoses FD leaks.

The goal is to enable us to regression test for things like

Modifications

- Add support for hooking socket and close calls.
- Wire up this support into the test harness.
- Extend the test harness to handle the logging.
- Add new regression test for #2047.

Results

We can write regression tests for FD leaks.

* Disable FD checking in most builds.

I'm doing this for speed reasons

* Always print the leaked fds number
2023-04-26 08:38:18 -07:00
David Nadoba 6720612111
Drop Swift 5.5 (#2406)
* Drop Swift 5.5

* Use `swift-atomics` 1.1.0 with `Sendable` adoption
2023-04-17 08:40:35 +01:00
Cory Benfield 61043a36f6
Work around the SwiftPM layout change. (#2389)
Motivation:

SwiftPM has changed its default layout for packages in
apple/swift-package-manager#6144. This breaks our CI, which assumes the
prior layout. We should work around this.

Modifications:

Enhance the code to tolerate both layouts.

Result:

Integration tests run on all platforms
2023-03-13 06:40:31 -07:00
Cory Benfield 1a0f46b8cd
Lift alloc counter Package.swift to 5.1 and add platforms (#2352)
Motivation:

Our allocation counter tests still build for 5.0 by default. This isn't
great, but we've been getting away with it because building for 5.7
requires changing the way we express our dependencies. Doing that is a
big breaking pain in the neck that requires changes in multiple repos.

As a shorter-term goal, however, to enable testing in at least one more
repo (swift-nio-ssh), this PR lifts the version to 5.1, which is the
last release compatible with the Package.swift dependency structure we
use but that supports the Platforms we need to express.

Modifications:

- Move allocation counter to 5.1
- Add platforms from swift-nio-ssh

Result:

We can write allocation counter tests for swift-nio-ssh.
2023-01-19 09:37:11 -08: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
David Nadoba 0b4edd8329
Add `NIOBSDSocket.ProtocolSubtype` (#2317)
* RawSocket prototype

* Conform `ProtocolSubtype` to `Hashable`

* Add public `NIOIPProtocol` type

Make `ProtocolSubtype` internal

* Subset of IANA protocols with an RFC

* Add `CustomStringConvertible` to `NIOIPProtocol`

* Add `init(_ rawValue: Int)`

* Rename `NIOBSDSocket.ProtocolSubtype.ip` to `.default`

* Add `NIOBSDSocket.ProtocolSubtype.mptcp`

and remove `NIOBSDSocket.mptcpProtocolSubtype`
2022-11-22 06:01:52 -08: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
Johannes Weiss 4ed8e1e228
rename class Lock to struct NIOLock (#2266) 2022-09-21 07:36:42 -07:00
David Nadoba 4fb6bf135b
Adopt `Sendable` for `CircularBuffer`, `MarkedCircularBuffer` and types in `NIOBSDSocket` namespace (#2097)
* Adopt `Sendable` for types in `BSDSocket` namespace

* Adopt `Sendable` for `CircularBuffer` and `MarkedCircularBuffer`

and also `Endianness`

* move `NIOSendable` into its own file and copy it over to syscall integration tests
2022-05-06 12:34:31 +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 d68066ccd7
Remove unnecessary extra swift file. (#2062)
The nightly builders have started automatically adding a struct with
@main to packages generated using swift package init. This is
interfering with our syscallwrapper tests, so we should delete that
file.
2022-03-08 08:08:47 -08:00
Si Beaumont be5fb3c170
Add benchmarks for copying CircularBuffer to Array (#2058)
Signed-off-by: Si Beaumont <beaumont@apple.com>

Co-authored-by: Cory Benfield <lukasa@apple.com>
2022-03-07 08:39:28 -08:00
Johannes Weiss a326de5a9c
atomics: make add/sub @discardableResult (#2048) 2022-02-17 08:03:12 -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 3a3e6cb9e3
Add benchmarks for copying BBV to Array. (#2037)
Motivation:

Protocols like Sequence have "private" hooks that can be implemented to
provide fast-paths for some operations. We missed a few on BBV, and I'd
like to add them. This is one use-case where they can help.

Modifications:

- Add an allocation-counter benchmark and a runtime benchmark for
  copying BBV to Array.

Result:

We have some benchmarks.
2022-02-03 01:36:12 -08:00
Franz Busch 51c3fc2e4a
Precondition that read doesn't return EINVAL (#2022)
### Motivation:

`read` should never return `EINVAL`. If it does return it though it is a bug inside NIO and we should precondition for it similar to what we do for `EBADF` & `EFAULT`. Closes https://github.com/apple/swift-nio/issues/1339

### Modifications:

This PR adds a new precondition for `EINVAL` and adds test that exercise this precondition.

### Result:

We are now preconditioning against `read` returning `EINVAL`.
2022-01-12 04:16:36 -08: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 d906b890d5
Add perf hooks for testing substring path. (#1976) 2021-10-13 12:08:37 +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
Cory Benfield b05c6f2206
Move NIO to NIOPosix, make NIO a shell. (#1936)
Motivation:

The remaining NIO code really conceptually belongs in a module called
NIOPosix, and NIOCore should really be called NIO. We can't really do
that last step, but we can prepare by pushing the bulk of the remaining
code into a module called NIOPosix.

Modifications:

- Move NIO to NIOPosix
- Make NIO an umbrella module.

Result:

NIOPosix exists.
2021-08-16 16:50:40 +01:00
Cory Benfield 4bb6acf57d
Move SocketAddress and NIOBSDSocket to NIOCore (#1907)
Motivation:

This is the next stage of our move of common interchange objects to
NIOCore and out of the NIO module. This time around we need
SocketAddress, which is part of the Channel API. Sadly, SocketAddress is
not as clean as some of the other ports, because it leaks a number of
POSIX-y concepts. This also forces us to bring along NIOBSDSocket, which
ideally we would not move, but we foolishly exposed as API on
SocketAddress.

Modifications:

- Move NIOBSDSocket API components into NIOCore.
- Split out the internal abstractions for NIOBSDSocket and leave those
  in NIO.
- Move SocketAddress into NIOCore.

Result:

SocketAddress will be sitting in NIOCore.
2021-07-22 17:48:14 +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
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 c5957f6760
Support multiple shared files in the allocation counter test framework (#1782)
Motivation:

The allocation counter test framework only supports a single shared
file which is quite limiting, especially if you rely on generated code.

Modifications:

- The '-s' option can now be passed multiple times
- The symlink name for any of the passed files will be the basename of
  the provided file rather than 'shared.swift'

Result:

Allocation counter test framework can use more than one shared file.
2021-03-16 18:38:39 +00:00
George Barnett 9451f4ac6f
Add synchronous channel options (#1755)
* Add synchronous channel options

Motivation:

The functions for getting and setting channel options are currently
asynchronous. This ensures that options are set and retrieved safely.
However, in some cases the caller knows they are on the correct event
loop but still has to pay the cost of allocating a future to either get
or set an option.

Modifications:

- Add a 'NIOSynchronousChannelOptions' protocol for getting and setting
  options
- Add a customisation point to 'Channel' to return 'NIOSynchronousChannelOptions'.
- Default implementation returns nil so as to not break API.
- Add implementations for 'EmbeddedChannel' and 'BaseSocketChannel'
- Allocation tests for getting and setting autoRead

Results:

Options can be get and set synchronously.
2021-02-22 11:07:30 +00:00
George Barnett 63d356819c
Add synchronous pipeline operations (#1741)
Motivation:

`ChannelPipeline` is explicitly thread-safe, any of the operations may
be called from outside of the channel's event loop. However, there are
often cases where it is known that the caller be on the right event
loop, and an asynchronous API is unnecessary.

In some cases -- such as when a pipeline is configured dynamically and
handlers are added from the 'channelRead' implementation of one handler
-- it forces the caller to write code that they might not actually need:
such as buffering events which may happen before the future completes.
This is unnecessary complexity when the caller knows that they must
already be on an event loop.

Modifications:

- Add a 'SynchronousOperations' view to the 'ChannelPipeline' which is
  available to callers via 'syncOperations'.
- Supported operations include: adding a handler, adding multiple
  handlers, retrieving a context via various predicates and retrieving a
  handler of a given type.
- Some of the operations in 'ChannelPipeline' were refactored to have an
  explicitly synchronous version, asynchronous versions complete their
  promise based on the result of these calls.
- Various minor documentation fixes and addition of 'self' where it was
  not used explicitly.

Result:

Users can perform synchronous operations on the 'ChannelPipeline' if
they know they are on the right event loop.
2021-02-09 09:59:41 +00:00
Johannes Weiss b021a5a5c6
alloc counters: Use atomic globals instead of thread-locals (#1743)
Motivation:

The alloc counters need to store the pointer to the original libc
implmentations of the hooked functions somewhere. Previously, we would
store them in thread locals. That works fine but creates quite some
overhead (and allocations) per thread (to do dlsym on every thread).

Modifications:

Instead, we now store the libc function pointers in (atomic) globals so
we need to only resolve each function once, no matter how many threads
we use.

Result:

Faster, and more accurate.
2021-02-08 15:28:50 +00:00
Cory Benfield 8ea768b0b8 Add static vars for common HTTP versions (#1723)
Motivation:

I'm sick of typing `.init(major: 1, minor: 1)`.

Modifications:

- Added static vars for common HTTP versions.

Result:

Maybe I'll never type `.init(major: 1, minor: 1)` ever again.
2021-01-19 17:27:02 +00:00
Peter Adams f4c87c800d
Remove an allocation from addHandlers (#1710)
* Add allocation test for adding multiple handlers

Motivation:

I believe there is at least 1 avoidable allocation in this area.
Even if there isn't, making sure we don't increase allocations is good.

Modifications:

Add a test of allocations when adding multiple handlers.
Set limits for docker images.

Result:

Allocations when adding multiple handlers are now checked.

* Remove an allocation from addHandlers

Motivation:

Fewer allocations should improve performance.

Modifications:

Split out a sub function from addHandlers.

I originally thought I'd have to change the part of this
function which reads `var handlers = handlers` as there was
a surprising allocation at the beginning of this function.
It seems that breaking out some of the logic is sufficient
to remove an allocation.

Result:

1 fewer allocation.

* Fix up alloc tests.
2020-12-21 13:54:28 +00:00
Cory Benfield e7880565aa
We use main as our development branch now. (#1651) 2020-09-24 18:02:44 +01:00
Peter Adams 74878a0235
Setup allocation test to send and receive ECN data. (#1594)
Motivation:

It's possible relaying ECN information will cause allocations.
Having a test which uses them will ensure this doesn't happen.

Modifications:

Added metadata data to always send ECN state and set a channel
option requesting to recieve it.

Result:

Allocation test will attempt to send and receive ECN data.
2020-07-14 18:02:47 +01:00
Saleem Abdulrasool 5de1e41310
NIO: Implement BSD sockets APIs for Windows (#1471)
Motivation:

Split out the internal implied BSD socket API code to allow alternative implementations of these interfaces on other platforms.

Modifications:

- Split the code apart.
- Provide POSIX and Windows implementations of the BSD socket API.

Result:

Should be easier to run NIO unmodified on Windows.
2020-07-03 10:14:36 +01:00
Peter Adams 8a865bd15e
Make UDP connection allocation test more like best practice code. (#1583)
Motivation:

There is at least a theoretical race to flush before close in prior version.
Having terrible code in the NIO repo is asking for someone to copy it.

Modifications:

flatMap the various parts of the client together which also ensures the
flush is complete before close is called.

Result:

Slightly nicer code, slightly fewer allocations.
2020-06-30 17:11:05 +01:00
Peter Adams a035a1b154
UDP allocation tests should not use so_reuseaddr (#1581)
Motivation:

so_reuseaddr on linux allows multiple binding to the same port simultaneously - this has not been seen to happen in practice but it is best to be cautious.

Modifications:

Remove address reuse from the UDP allocation tests.

Result:

Reduced danger of binding the same port twice.
2020-06-29 16:51:42 +01:00
Peter Adams 16b9dd6a61
Stop udp connection allocation test hanging on linux. (#1578)
Motivation:

Hanging tests make doing work and asserting correctness very difficult.

Modifications:

Remove address reuse from the server side of the udp channel.

Result:

The tests no longer hang.

(The reason things we hanging was that the client side was occasionally getting assigned the same port number as the server side (extremely agressive port reuse)
2020-06-29 12:42:48 +01:00
Johannes Weiss 3a2fc0d39b
alloc tests: implement malloc_zone_* (#1569)
Motivation:

The Swift runtime is now using malloc_zone_*, we need to implement
replacements for these too. This is just a first pass, eventually, we
should implement _all_ replacements as `malloc_zone_memalign` which is
powerful enough to implement all others.

Modifications:

Provide new replacements.

Result:

Alloc tests work again on macOS.

Co-authored-by: Cory Benfield <lukasa@apple.com>
2020-06-26 11:04:37 +01:00
Cory Benfield 669a19cb7b
Set SO_LINGER in integration tests. (#1549)
Motivation:

We now have sufficiently many integration tests that the number of TCP
sockets in TIME_WAIT begins to cause resource pressure on the system.
This can lead to the integration tests failing due to being unable to
assign a socket.

We can force this to not happen by disabling linger. As we're running on
a lossless fabric (localhost), this is entirely safe.

Modifications:

- Disable TIME_WAIT for integration tests.

Result:

Integration tests will pass.

Co-authored-by: Johannes Weiss <johannesweiss@apple.com>
Co-authored-by: Peter Adams <pp_adams@apple.com>
2020-06-24 14:28:40 +01:00
Johannes Weiss 01e0e0cef4
stablise 1000 TCP connections alloc test (#1566)
Motivation:

The 1000 TCP connections allocation counter test did way too many thread
crosses and other things that allocated for unrelated reasons.

Modifications:

Remove those.

Result:

Much more stable
2020-06-23 13:11:43 +01:00
Peter Adams c03dd9c5f1
Make allocation tests produce more stable results (#1565)
Motivation:

Allocation tests are very hard to use productively if they don't produce stable results.

Modifications:

Change TCP and UDP connection tests to monitor on the server side as well as the client side to make sure all data is completely send and received before stopping counting allocations.

Result:

Allocation tests are more stable than before.
2020-06-23 10:25:36 +01:00
Johannes Weiss 5268726898
fix inappropriate lanugage in NIO (#1554)
Motivation:

It's 2020, we shouldn't use unnecessary offensive, insulting, or
outdated language.

Modifications:

Fix a few examples.

Result:

More inclusive.
2020-06-12 19:34:05 +01:00
Johannes Weiss e57122bd89
ByteBuffer: add convenience initialisers (#1533)
Motivation:

There are multiple sub-optimal ByteBuffer creation patterns that occur
in the wild. Most often they happen when people don't actually have
access to a `Channel` just want to "convert" a `String` into a
`ByteBuffer`. To do this, they are forced to type

    var buffer = ByteBufferAllocator().buffer(capacity: string.utf8.count)
    buffer.writeString(string)

Sometimes, they don't get the capacity calculation right or just put a
`0`.

Similar problems happen if NIO users want to cache a ByteBuffer in their
`ChannelHandler`. You will then find this code:

```swift
if self.buffer == nil {
    self.buffer = receivedBuffer
} else {
    var receivedBuffer = receivedBuffer
    self.buffer!.writeBuffer(&receivedBuffer)
}
```

And lastly, sometimes people want to append one `ByteBuffer` to another
without mutating the appendee. That's also cumbersome because we only
support a mutable version of `writeBuffer`.

Modifications:

- add `ByteBuffer` convenience initialisers
- add convenience `writeBuffer` methods to `Optional<ByteBuffer>`
- add `writeBufferImmutable` which doesn't mutate the appendee.

Result:

More convenience.

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

Co-authored-by: Cory Benfield <lukasa@apple.com>
2020-06-04 21:02:11 +01:00
Johannes Weiss 2450ba55e5
crash tester test suite (#1536)
Motivation:

It's often very important to test that in certain cases we actually
crash with a certain error message whilst having access to all of NIO.

Modifications:

Add a crash tester test suite.

Result:

We can test crashers.
2020-06-01 12:51:39 +01:00
Peter Adams 1d134ccdcc
Fine grained UDP allocation tests (#1534)
Fine grained UDP allocation tests

Motivation:

The existing UDP allocation tests count allocations everywhere.

Split out 3 tests to cover:

Making connections.
Making bootstraps.
Transferring data.
Modifications:

Three new tests.

Result:

Easier to debug changes to allocation profiles in UDP.
2020-05-29 12:49:34 +01:00
Peter Adams 51370e4113
Finer grained allocation tests (#1531)
Motivation:

The existing tcp allocation tests cover everything from bootstrap creation through to sending data in one massive test. The parameters of how many iterations control the focus of the test. It would be better to be more explicit about what we're trying to test.

Modifications:

2 new tests:
   * client bootstrap creation.
   * connection establishment.
 (Data transfer is already covered by the ping_pong test)

Result:

Easier to assess the impact of changes to memory allocation patterns.
2020-05-28 16:17:20 +01:00
Johannes Weiss 36bf78a1e9
fix linker check test (#1519)
Motivation:

The linker test script that checks what libraries we link was totally
broken.

Modifications:

Fix the linker test script.

Result:

We can correctly determine what we link and what not.
2020-05-13 20:48:57 +01:00
Cory Benfield 30265d69a8
Adjust names of BSDSocket option values. (#1510)
Motivation:

The names of most of the BSD socket option values were brought over into
their NIO helper properties, with their namespace removed. This vastly
increases the risk of collision, particularly for things like TCP_INFO,
which just became .info.

Modifications:

- Added the prefixes back, e.g. `.info` is now `.tcp_info`.
- Renamed socket type `.dgram` to `.datagram`, as this is the nice clean
  API and we should use nice clean names.

Result:

Better APIs
2020-05-11 15:13:58 +01:00
Peter Adams 9afac5ecda
UDP based allocation tests (#1496)
UDP based allocation tests (#1496)

Motivation:

With future work being considered in the UDP space it will be useful to have a baseline measure of allocations.

Modifications:

New allocation tests for UDP -
Ideas inspired by the TCP allocation tests.
Code a modified version of UDPEchoServer and UDPEchoClient examples.

Result:

There are UDP based allocation tests.

Co-authored-by: Cory Benfield <lukasa@apple.com>
Co-authored-by: Johannes Weiss <johannesweiss@apple.com>
2020-05-04 11:36:23 +01:00
Peter Adams e8ec02602c
Remove a warning from the performance test build. (#1481) 2020-04-16 18:22:53 +01:00