Commit Graph

1930 Commits

Author SHA1 Message Date
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
Johannes Weiss 28850a539b
ELF: provide flatMapWithEventLoop and friends (#1996) (#2049) 2022-02-17 10:08:04 -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
Sebastian Vogt 154f1d3236
Implement BBV custom contains function. (#2044) 2022-02-09 13:05:28 +00:00
Stepan Ulyanin d1814ea5cf
replace the double encoding by writing bytes directly to the buffer (#2043)
Co-authored-by: Cory Benfield <lukasa@apple.com>
2022-02-08 23:41:13 -08:00
Sebastian Vogt 7000510fd7
Add benchmark for BBV contains. (#1385) (#2042)
* Add ByteBufferView contains benchmark.

* Add ByteBufferView contains benchmark.

* Add ByteBufferView contains benchmark.
2022-02-08 22:06:21 -08:00
Gwynne Raskind 7ec0281c1f
`Substring.UTF8View` began implementing `Collection.withContiguousStorageIfAvailable(_:)` starting in Swift 5.3. Update `ByteBuffer.setSubstring(_:at:)` to use it to avoid a conversion to `String` in the common case. (#1975)
Co-authored-by: George Barnett <gbarnett@apple.com>
Co-authored-by: Cory Benfield <lukasa@apple.com>
2022-02-07 06:24:48 -08:00
Cory Benfield 4ad4c11526
Improve the performance of copying BBV (#2039)
Motivation:

When turning a BBV into a Collection, several of the collection
algorithms can do better if you implement the semi-private
`_copyContents` hook. We can easily implement it, so we should. While
I'm here we should clean up some other bits.

Modifications:

- Implement _copyContents.
- Implement a faster `.count` for `ByteBufferView`.
- Make `ByteBuffer.capacity` `@inlinable` to reduce ARC traffic

Result:

Copying a BBV into an Array is faster.
2022-02-07 12:40:29 +00:00
Sebastian Vogt a4ad5eb54d
Allow NIOEchoClient to receive fragmented echo responses. (#2041)
* Add buffering for reading data

* Simplify channelRead in NIOEchoClient

* Remove spacing
2022-02-07 01:35:16 -08:00
David Nadoba 4f2c6a3e0b
Add `collect(upTo:) -> ByteBuffer` and variations to `AsyncSequence` (#2038) 2022-02-03 10:31:09 -08: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
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 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
Johannes Weiss a94e7ccf34
nio-diagnose: list all thread names (#2030) 2022-01-10 15:48:57 +00:00
buttaface 0467886d0b
Get Android constants used by Channel from Bionic instead (#2026)
Motivation:

An upcoming pull, apple/swift#35707, moves Android to the same single-header
modulemap for Bionic as used on linux, but that doesn't work unless this is
changed. This approach works both with the current release toolchain and
with that new modulemap.

Modifications:

Change how these Bionic constants are imported.

Result:

This repo compiles for Android and the tests pass with both modulemap approaches.

Co-authored-by: Cory Benfield <lukasa@apple.com>
2022-01-06 09:45:46 +00:00
Cory Benfield b337796bdd
Update soundness script for 2022 (#2027) 2022-01-05 09:54:25 -08:00
Franz Busch c2cabf4c9d
Guarantee ordering of `scheduleTask` with same deadline (#2020)
### Motivation:

When scheduling tasks with the same deadline the current order of execution is undefined. Fixes https://github.com/apple/swift-nio/issues/1541

### Modifications:

In my previous PR https://github.com/apple/swift-nio/pull/2010, I added an internal id to every `ScheduledTask` to give them an identity for cancellation purposes. In this PR, I am now using the same id to also ensure that the execution of tasks with the same deadline is the same as the order they were scheduled in.

### Result:

`ScheduledTask`s are now executed in their scheduled order when they have the same deadline.
2022-01-04 05:48:51 -08:00
Boby f5da374e27
Correct spelling of foreseeable in README.md (#2024)
Minor spelling mistake.
2022-01-03 20:35:33 +00:00
Franz Busch acbd697113
Conform `AddressedEnvelope` conditionally to `Hashable` & `Equatable` (#2017)
### Motivation:

Sometimes, it is nice to check `AddressedEnvelope`s for equality or hash them. Especially, in tests this comes in handy.

### Modifications:

This PR, adds conditional conformances to `AddressedEnvelope` for `Equatable` and `Hashable` depending on its generic `DataType` .

I also added a new module `NIOCoreTests` which was an open todoleft from the creation of the `NIOCore` module. To not add more tests that we have to migrate in the future, I started to create the new tests in the new module right away. I also created issue https://github.com/apple/swift-nio/issues/2016, to keep track of our open task to move the other tests over.

### Result:

`AddressedEnvelope` is conditionally `Equatable` and `Hashable`
2021-12-20 10:22:13 -08:00
Fabian Fett e123c216cc
Add canImport(_Concurrency) for Xcode 13.0 (#2015) 2021-12-20 15:12:50 +00:00
tomer doron b5c662adfc
Update doc script to match latest source-kitten (#2013)
motivation: fix broken doc generation script

changes:
* pass the --spm flag now required by source-kitten
* update location of source-kitten source to make it more robust
* update list of module to generate docs for to match the structural changes in nio
2021-12-16 09:28:39 +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
Johannes Weiss 094cd8c6e8
nio-diagnose script (#2008)
Motivation:

Frequently when folks have issues with SwiftNIO or related technologies,
we need to ask the same questions over and over again.

It'd be much nicer to just have a script that collects them.

Modifications:

Add `scripts/nio-diagnose`.

Result:

Users/devs can easily create nio-diagnose files which are markdown and
can easily be pasted into GH.
2021-12-10 11:02:29 -08:00
Cory Benfield fa79f8d895
Enable io_uring builds with newer liburing (#2006)
Motivation:

Newer copies of liburing have changed header imports, making some
of our implicit includes fail, and have also changed the types
of some methods in a way that would only produce warnings in C but
which produces errors in Swift. Additionally, liburing broke when
we did the module split, but we didn't notice.

Modifications:

- Import NIOCore for the Uring Swift code.
- Import poll.h in CNIOLinux
- Support arguments that are either pointers or UInt64s.

Results:

liburing code compiles again
2021-12-09 09:19:12 +00:00
Paul Schmiedmayer fa3b2a2e66
Adds Swift Concurrency Availability to macOS 10.15, iOS 13, tvOS 13, and watchOS 6 (#2004)
* Change Swift Concurrency Availability

* Label GitHub Action Jobs

* Incorporate the insights from Johannes Weiss

* Remove GitHub Actions

* Incorporate the feedback of Cory Benfield

Co-authored-by: Cory Benfield <lukasa@apple.com>
2021-12-03 17:35:01 +00:00
Johannes Weiss 0697d5a599
remove/deprecate the file:line: parameters from flatMap and friends (#1998)
Motivation:

For NIO's 'promise leak detector' we added file:line: labels to
makePromise and there it makes sense. A user might create a promise and
then never fulfil it, bad. With the file:line: arguments we can give
good diagnostics.

However, we (probably that @weissi again) also added it to flatMap and
friends where it doesn't make sense at all.

Sure, EventLoopFuture's implementation may create a promise in the
implementation of flatMap but this promise is never leaked unless the
previous future is never fulfilled (or NIO has a terrible bug). Suffice
to say that in a future chain, it's never a flatMap etc which is
responsible for leaking the first promise...

Explain here the context, and why you're making that change.
What is the problem you're trying to solve.

Modifications:

Remove all unnecessary `file:line:` parameters whilst keeping the public
API intact.

Result:

More sensible code.
2021-12-03 08:27:55 -08:00
Johannes Weiss 773b3797d7
provide EventLoopGroup.any() which is sticky to the current EventLoop (#2003)
Motivation:

A lot of libraries that use SwiftNIO don't allow/require the user to
specify what `EventLoop`s a certain function runs on. Something like

```
myHTTPClient.get("https://example.com) -> EventLoopFuture<...>
```

Internally `MyHTTPClient` has not much choice but using the
`EventLoopGroup.next()` method to obtain an `EventLoop` on which to
create the `EventLoopFuture` (that is returned).

This all works fine but unfortunately it usually forces a thread switch
which is most of the time avoidable if we're already running on an
`EventLoop`.

Modifications:

Provide an `EventLoopGroup.any()` method which can be used like so:

```swift
func get(_ url: String) -> EventLoopFuture<Response> {
    let promise = self.group.any().makePromise(of: Response.self)

    [...]

    return promise.futureResult
}
```

`EventLoopGroup.any()` very much works like `EventLoopGroup.next()`
except that it tries -- if possible -- to return the _current_
`EventLoop`.

Note that this means that `any()` is _not_ the right solution if you
want to load balance. Likely, everything will now stay on the same
`EventLoop`.

Result:

Fewer thread switches.
2021-12-03 13:10:21 +00:00
Cory Benfield d3a65106b2
Don't tolerate EBADF on close. (#2002)
Motivation:

It's like that #1999 was a little wide, and we should have forbidden
EBDAF on close.

Modifications:

Still forbid EBADF on close.

Result:

EBADF still preconditions on close.
2021-12-03 09:34:17 +00:00
John Connolly b465de0663
relax-precondition (#1999)
* relax-precondition

* Explanatory comment.

Co-authored-by: Cory Benfield <lukasa@apple.com>
2021-12-03 08:31:38 +00:00
Johannes Weiss d08e8ff938
disable PTHREAD_MUTEX_ERRORCHECK in release mode (#1995)
Motivation:

`pthread_mutex_t` locks can do advanced error checking with
`PTHREAD_MUTEX_ERRORCHECK`, the cost of which was unknown. With #1994 I
could now measure it.

The differences from my local machine (M1 MBP) for uncontended locks
are:

- on Linux: 10% faster without `PTHREAD_MUTEX_ERRORCHECK`
- on macOS: 25% faster without `PTHREAD_MUTEX_ERRORCHECK`!

Modification:

Do the extended error checking only in debug mode. Note that we still
`precondition` on all pthread return values (which is basically free).

Result:

Faster code.

Co-authored-by: Cory Benfield <lukasa@apple.com>
2021-11-29 09:49:07 +00:00
Johannes Weiss 2ef5cbee6b
benchmarks: lock performance for 1, 2, 4, 8 threads wanting lock (#1994)
Motivation:

To judge the cost of `PTHREAD_MUTEX_ERRORCHECK` as well as
`os_unfair_lock` vs `pthread_mutex_t` it's useful to have a few simple
benchmarks.

Modification:

Add lock benchmarks.

Result:

Better data.
2021-11-29 09:07:40 +00:00
Cory Benfield 37e7a33de4
Fix testSchedulingTaskOnSleepingLoopWakesUpOnce (#1992)
Motivation:

This test is flaky, and has always been flaky.

The issue here is simply a timing one. It has always been possible
for the thread running in the background DispatchQueue to be take
longer between calling semaphore.signal and promise.cascade(to:)
than it does for the event loop to process the tasks. If that
happens, this test will fail by eventually timing out.

Modifications:

- Adjust the test to avoid using promise.cascade(to:), and so prevent it
  from having at timing window.

Result:

The test will be not flaky, or at least less flaky.

Resolves #1971.

Co-authored-by: George Barnett <gbarnett@apple.com>
2021-11-25 10:04:25 +00:00
Fabian Fett 926fe9de58
Read and write null terminated strings (#1990) 2021-11-24 11:33:51 +00:00
Johannes Weiss a58c36c55c
ByteBuffer: reduce unnecessary bounds & under/overflow checks (#1988)
Motivation:

ByteBuffer is quite core to NIO programs' perf and yet it doesn't even
try to reduce the number of under/overflow & bounds checks.

That's a lot of code that will never be run and that also introduces
unncessary branches which hurt perf.

Modification:

Remove a bunch of low hanging fruit checks.

Result:

Faster (and less) code.
2021-11-22 16:32:47 +00:00
Johannes Weiss b2629903ca
ByteBuffer: provide multi read/write int methods (#1987)
Motivation:

Many network protocols (especially for example NFS) have quite a number
of integer values next to each other. In NIO, you'd normally parse/write
them with multiple read/writeInteger calls.

Unfortunately, that's a bit wasteful because we're checking the bounds
as well as the CoW state every time.

Modifications:

- Provide read/writeMultipleIntegers for up to 15 FixedWidthIntegers.
- Benchmarks

Result:

Faster code. For 10 UInt32s, this is a 5x performance win on my machine,
see benchmarks.
2021-11-22 14:58:52 +00:00
Fabian Fett addf69cfe6
Allow HTTP Server to send multiple informational heads before actual response head (#1985)
Co-authored-by: Helge Heß <devteam@zeezide.de>
Co-authored-by: Tobias Haeberle <tobias.haeberle@holidu.com>

Co-authored-by: Helge Heß <devteam@zeezide.de>
Co-authored-by: Tobias Haeberle <tobias.haeberle@holidu.com>
2021-11-09 10:20:51 +00:00
Fabian Fett 7a36304aa4
[HTTPDecoder] Decode informational http response head correctly (#1984)
Motivation:
- Currently http 1xx response heads are handled incorrectly

Modifications:
- Add an `InformationalResponseStrategy` that allows the user to specify whether http 1xx responses shall be forwarded or dropped. 
- Implement the necessary cases in `HTTPDecoder` and `BetterHTTPParser`

Co-authored-by: Cory Benfield <lukasa@apple.com>
2021-11-08 19:41:08 +01:00
Adam Fowler 697503677d
Conform EventLoopFuture/Promise to Sendable (#1982)
* Conform EventLoopFuture/Promise to Sendable

* Only conform to Sendable if concurrency is available

* Add NIOSendable
2021-11-01 09:29:04 +00:00
Johannes Weiss 7994117168
force getSlice to be inlined into readSlice (#1981) 2021-10-26 10:33:18 +01:00
Johannes Weiss 4ec22484cd
ByteBuffer: shrink getSlice (#1980)
Motivation:

I noticed that when replacing `_UInt24` to `UInt32` in `ByteBuffer`'s
code (which unfortunately increases its size and is therefore
unacceptable), then `getSlice` gets fully inlined into `readSlice`.

But in the normal `ByteBuffer` code (with `_UInt24`) that is not the
case. So I had a quick go a shrinking the `getSlice` code. Sadly, it's
still not quite enough to get `getSlice` inlined into `readSlice`.

There are quite a lot of extra shifts for the UInt32 <--> UInt24
conversions and an extra branch (to check the `sliceBeginIndex >= 16
MiB` condition).

Modifications:

- use unchecked arithmetic where safe
- outline the slow path

Result:

much smaller code size
2021-10-26 09:56:29 +01:00
Fabian Fett ea7d9b50c9
[ByteBuffer] Replace use of .map with guard in Data read (#1979) 2021-10-25 10:36:49 +02:00
Fabian Fett 269a61727e
[ByteBuffer] Reduce ARC traffic when reading (#1978)
In my local testing I have seen that the compiler adds a retain and release cycle around the use of `Optional.map` in ByteBuffer's read methods.

Modifications:
- Replaced the use of `Optional.map` with `guard let` in ByteBuffer's read methods.
2021-10-21 16:57:25 +02:00
Antwan van Houdt 787e2287d0
Remove not on eventLoop precondition for NIOPipeBootstrap (#1977)
Motivation:

Currently you cannot create a NIOPipeBootstrap when you are on
an event loop due to a precondition check. This check seeks to prevent
consumers of the API from passing in a file descriptor thats referencing
a file on disk or on the network.

The method at hand 'validateFileDescriptorIsNotAFile' uses fstat, which potentially
could block the event loop especially if the fd is referencing a file over the network.
This check however prevents certain use cases of SwiftNIO, where the downsides
of a consumer of this api blocking their own event loop do not weigh in against preventing
an entire use case from SwiftNIO.

Modifications:

Removed the precondition

Result:

After this change it will be possible to feed file descriptors into
the bootstrap which potentially block the current event loop.
A potential (portable) replacement for fstat still has to be found in order to solve this problem completely.
2021-10-18 13:02:07 +01:00
Cory Benfield d906b890d5
Add perf hooks for testing substring path. (#1976) 2021-10-13 12:08:37 +01:00
Cory Benfield 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
Fabian Fett 6aa9347d9b
Readd module _NIOConcurrency to not break adopters (#1970) 2021-09-23 16:50:53 +02:00
Fabian Fett 9e1552ceaf
Move AsyncAwait helpers into NIOCore (#1969)
- Moved the `AsyncAwaitSupport.swift` to `NIOCore`
- Removed the `_NIOConcurrency` target
2021-09-23 14:14:49 +02:00