Commit Graph

51 Commits

Author SHA1 Message Date
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
David Nadoba c7b4989b02
Remove `#if compiler(>=5.5)` (#2292)
### Motivation
We only support Swift 5.5.2+.

### Modification
Remove all `#if swift(>=5.5)` conditional compilation blocks.

### Result
less branching
2022-10-13 07:17:46 -07:00
Johannes Weiss 4ed8e1e228
rename class Lock to struct NIOLock (#2266) 2022-09-21 07:36:42 -07:00
Franz Busch f144292e5d
Implement a `NIOAsyncWriter` (#2251)
* Implement a `NIOAsyncWriter`

# Motivation
We previously added the `NIOAsyncProducer` to bridge between the NIO channel pipeline and the asynchronous world. However, we still need something to bridge writes from the asynchronous world back to the NIO channel pipeline.

# Modification
This PR adds a new `NIOAsyncWriter` type that allows us to asynchronously `yield` elements to it. On the other side, we can register a `NIOAsyncWriterDelegate` which will get informed about any written elements. Furthermore, the synchronous side can toggle the writability of the `AsyncWriter` which allows it to implement flow control.
A main goal of this type is to be as performant as possible. To achieve this I did the following things:
- Make everything generic and inlinable
- Use a class with a lock instead of an actor
- Provide methods to yield a sequence of things which allows users to reduce the amount of times the lock gets acquired.

# Result
We now have the means to bridge writes from the asynchronous world to the synchronous

* Remove the completion struct and incorporate code review comments

* Fixup some refactoring leftovers

* More code review comments

* Move to holding the lock around the delegate and moved the delegate into the state machine

* Comment fixups

* More doc fixes

* Call finish when the sink deinits

* Refactor the writer to only yield Deques and rename the delegate to NIOAsyncWriterSinkDelegate

* Review

* Fix some warnings

* Fix benchmark sendability

* Remove Failure generic parameter and allow sending of an error through the Sink
2022-09-21 02:53:53 -07:00
Si Beaumont 9294f8da3b
NIOPerformanceTester: Increase operations used in lock benchmarks from 1M to 10M (#2121) 2022-05-18 10:53:51 +01:00
Si Beaumont 771257cc23
NIOPerformanceTester: Add DeadlineNowBenchmark for NIODeadline.now() (#2117)
* NIOPerformanceTester: Add DeadlineNowBenchmark for NIODeadline.now()

Signed-off-by: Si Beaumont <beaumont@apple.com>

* fixup: Return counter from benchmark

Signed-off-by: Si Beaumont <beaumont@apple.com>
2022-05-16 19:21:31 +01:00
Si Beaumont 684c09315f
Use unbuffered IO for stdout in NIOPerformanceTester (#2072)
* Use unbuffered IO for stdout in NIOPerformanceTester

Signed-off-by: Si Beaumont <beaumont@apple.com>

* CRASH PERF TESTS: Up task count to 1M to test logging change

* Revert "CRASH PERF TESTS: Up task count to 1M to test logging change"

This reverts commit d8fa50eb15.

Co-authored-by: Cory Benfield <lukasa@apple.com>
2022-04-20 13:16:14 -07:00
Si Beaumont 1af9615110
Increase runtime of performance tests to O(10 ms) to increase SNR (#2063)
Signed-off-by: Si Beaumont <beaumont@apple.com>
2022-03-24 07:42:24 -07: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
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
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 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 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
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
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 64285cbff2
Clean up dependencies and imports. (#1935)
Motivation:

As we've largely completed our move to split out our core abstractions,
we now have an opportunity to clean up our dependencies and imports. We
should arrange for everything to only import NIO if it actually needs
it, and to correctly express dependencies on NIOCore and NIOEmbedded
where they exist.

We aren't yet splitting out tests that only test functionality in
NIOCore, that will follow in a separate patch.

Modifications:

- Fixed up imports
- Made sure our protocols only require NIOCore.

Result:

Better expression of dependencies.

Co-authored-by: George Barnett <gbarnett@apple.com>
2021-08-12 13:49:46 +01:00
Maxim Zaks cf054f27b5
Add performance test for web socket client random request key (#1863)
* Add performance test for web socket client random request key

* use `reduce` function to minimise memory consumption of the test

Co-authored-by: Cory Benfield <lukasa@apple.com>
2021-06-01 11:08:13 +01:00
Johannes Weiss e0963def86
bring back accidental commented benchmark (#1833)
Motivation:

In #1733 I accidentally commented out a perf benchmark (who knows why).

Modification:

Bring it back.

Result:

Benchmark is back.

Co-authored-by: Cory Benfield <lukasa@apple.com>
2021-04-29 12:06:57 +01:00
Johannes Weiss c5a214f075
B2MD: Don't try to reclaim if continuing to parse (#1733)
Motivation:

B2MD called out to the decoder's `shouldReclaimBytes` after every
parsing attempt, even if the parser said `.continue`.

That's quite pointless because we won't add any bytes into the buffer
before we're trying the parser again.

Modifications:

Only ask the decoder if we should reclaim bytes if the decoder actually
says `.needMoreData`.

Result:

Faster, better, more sensible.
2021-01-29 17:03:04 +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 b671e557fd
Only use ascii characters in perf test names. (#1718)
Motivation:

Many other systems don't like non ascii characters.

Modifications:

Change a letter 'a' to a letter 'a' but with a more normal encoding.

Result:

Test names should be in ascii
2021-01-11 07:32:39 +00:00
Johannes Weiss fe10c5c063
Change the `class` restriction on our protocols to `AnyObject` (#1702)
Motivation:

In all contemporary Swift versions, the `class` and the `AnyObject`
protocol restriction is the same. And `class` is deprecated which warns
on newer Swift compilers.

Modifications:

Replace `class` with `AnyObject`.

Result:

No warnings on newer Swift compilers.
2020-12-09 19:43:11 +00: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
Saleem Abdulrasool bcc180dab6
Add new `BSDSocket` namespace (#1461)
* NIO: Add new `BSDSocket` namespace

This starts the split of the POSIX/Linux/Darwin/BSD interfaces and the
BSD Socket interfaces in order to support Windows.  The constants on
Windows are not part of the C standard library and need to be explicitly
prefixed.  Use the import by name to avoid the `#if` conditions on the
wrapped versions.  This will allow us to cleanly cleave the dependency
on the underlying C library.

This change adds a `BSDSocket.OptionLevel` and `BSDSocket.Option` types
which allow us to get proper enumerations for these values and pipe them
throughout the NIO codebase.

* Apply suggestions from code review

Co-Authored-By: Cory Benfield <lukasa@apple.com>
2020-04-02 19:06:48 +01:00
Johannes Weiss c6e5fe88e1
ByteBuffer: make getInteger for UInt8 faster (#1380)
Motivation:

getInteger used the normal, generic implementation for UInt8s, however
they can be made considerably faster by using a specialised method.
ByteBufferIterator was also affected by this.

Modifications:

Use a specialised version for UInt8s for getInteger.

Result:

- ByteBufferView can be iterated about 20% faster.
2020-02-06 11:59:10 +00:00
Johannes Weiss 74944a937d
use Optional<T> instead of T? to workaround SR-11777 (#1252)
Motivation:

In Swift, writing

    var something: T?

    init() {
        self.something = someValue
    }

means that the compiler will first set `self.something` to `nil` and
then in the init override it with `self.someValue`
(https://bugs.swift.org/browse/SR-11777). Unfortunately, because of
https://bugs.swift.org/browse/SR-11768 , stored property initialisation
cannot be made `@inlinable` (short of using `@frozen` which isn't
available in Swift 5.0).

The combination of SR-11768 and SR-11777 leads to `var something: T?`
having much worse code than `var something: Optional<T>` iff the `init`
is `public` and `@inlinable`.

Modifications:

Change all `var something: T?` to `var something: Optional<T>`

Result:

Faster code, sad NIO developers.
2019-11-27 18:37:38 +00:00
Richard Low b1834d4459 Add withContiguousStorageIfAvailable implementation to WebSocketMaskingKey (#1237)
Motivation:

It's faster and contiguous storage is trivially available

Modifications:

- Implement WebSocketMaskingKey.withContiguousStorageIfAvailable
- Make it @inlinable, requiring promoting WebSocketMaskingKey.key to internal
  so renamed to _key.

Result:

Writing WebSocketMaskingKey into ByteBuffer is about 2x faster.
2019-11-12 17:59:04 +00:00
Emil Marashliev 8aff50a5e5 Add extra WebSocket decoder benchmarks (#1219)
Motivation:

We want to have some extra WebSocket decoder benchmarks, for
 a WebSocketFrame with a maskingKey, a WebSocketFrame with a 16-bit
 length and a WebSocketFrame with a 64-bit length

Modifications:

Changed WebSocketFrameDecoderBenchmark to have ability for dynamic
 WebSocketFrame length through the initializer parameter dataSize.
Added ability for WebSocketFrameDecoderBenchmark to benchmark
 a WebSocketFrame with a maskingKey by passing withMaskKey parameter to
 the initializer.
Added new benchmarks in the main for WebSocketFrame decoding with a
 16-bit length, WebSocketFrame decoding with a 64-bit length and with
 a maskingKey.

Result:

Better WebSocket decoder benchmarks
2019-11-11 16:08:12 +00:00
Richard Low 94e9bc1912 Speed up ByteBuffer setBytes slow path (#1231)
Motivation:

When calling ByteBuffer setBytes/writeBytes with CircularBuffer<Uint8> we take the slow path. Before we make any changes we want a baseline for current performance.

Modifications:

- This gives a very significant performance increase for CircularBuffer
and likely other types that use the slow path.
- Adds ByteBuferBenchmark.swift and tests circular_buffer_into_byte_buffer_1kb, circular_buffer_into_byte_buffer_1mb.
- Make _setSlowPath @inlinable
- Implement == for CircularBuffer.Index to make it @inlinable

Result:

- Extra performance tests
- Improve performance
2019-11-11 15:09:39 +00:00
Johannes Weiss 4297ed4b5d NIOPerformanceTester: more precision and resiliency (#1229)
Motivation:

Previously, NIOPerformanceTester would use Foundation.Date twice to
calculate the time spend in a given function. This is less precise as it
can be but more importantly, it's not resilient against the user
changing the clock or the computer going to sleep.

Modifications:

Use DispatchTime.now().uptimeNanoseconds

Result:

More precise and resilient benchmark measurements.
2019-11-11 10:19:29 +00:00
Emil Marashliev 08b9d59573 Add an benchmark for WebSocket frame decoder (#1203)
Motivation:

It's important to know how websocket frame decoder perform.

Modification:

- Wrote simple benchmark for WebSocket frame decoding.

Result:

Better insight
2019-10-30 14:01:05 +01:00
Johannes Weiss 2fe1154d4f fix new Swift compiler warnings (#1170)
Motivation:

Very recent Swift compilers have more warnings.

Modifications:

Fix the warnings.

Result:

No warnings when compiling.
2019-10-19 13:09:29 -07:00
Cory Benfield 55ed652a78
Save the performance tests from the OOM killer (#1164)
Motivation:

A dark force walks abroad our lands. In a place where well-behaved
processes close their blinds, lock their doors, and try not to make
noise late at night, processes that shine just a little too brightly,
consume just a little too much RAM, attract the attention of a dark
force whose name is spoken only in whispers. Some call this force a
myth, but others say that the deniers of this force have whispered dark
incantations, invoking the power word "oom_adj".

It is time we intervened to keep the law-abiding processes in our CI
systems safe.

Modifications:

- Prevent the websocket performance tests comnsuming 4GB of RAM.

Result:

Peace will reign.
2019-10-15 14:03:27 +01:00
Cory Benfield 37873bb265 Add some websocket encode benchmarks. (#1159)
Motivation:

To improve the performance of a given component it is very helpful to
know how it performs! This patch adds benchmarks and allocation counter
tests to NIO for websocket frame encoding.

Modifications:

- Wrote some benchmarks for WebSocket frame encoding.
- Wrote some allocation counter tests for WebSocket frame encoding.
- Extend the allocation counter tests to properly account for sub-tests

Result:

Better insight
2019-10-11 16:04:08 +01:00
Johannes Weiss e38f1b695a apply suggestions from #1117 (#1118)
Motivation:

@ravikandhadai suggested some minor changes in #1117 which we should
apply.

Modifications:

Apply all suggested changes all over the code base.

Result:

- fixes #1117
2019-08-20 09:24:58 +01:00
Johannes Weiss 6b20fa5ce8
add two ELF.reduce benchmarks (#1069)
Motivation:

As #1054 shows, we have some low-hanging performance fruit regarding
off-EventLoop future reduces. We should quantify those.

Modifications:

Add benchmarks to quantify the potential wins.

Result:

More benchmarks.
2019-07-17 12:13:40 +01:00
Johannes Weiss 7f20464df3 enable TCP_NODELAY by default (#1020)
Motivation:

Networking software like SwiftNIO that always has explicit flushes
usually does not benefit from having TCP_NODELAY switched off. The
benefits of having it turned on are usually quite substantial and yet we
forced our users for the longest time to enable it manually.

Quite a bit of engineering time has been lost finding performance
problems and it turns out switching TCP_NODELAY on solves them
magically.

Netty has made the switch to TCP_NODELAY on by default, SwiftNIO should
follow.

Modifications:

Enable TCP_NODELAY by default.

Result:

If the user forgot to enable TCP_NODELAY, their software should now be
faster.
2019-06-19 18:04:01 +01:00
Johannes Weiss 2f98289125
ChannelPipeline benchmark (#1002)
Motivation:

We need good microbenchmarks.

Modifications:

Add a ChannelPipeline microbenchmark.

Result:

More benchmarks.
2019-05-30 13:26:25 +01:00
Daniel Alm 77d90255eb Significantly improve the performance of `EventLoopFuture.{and,when}AllSucceed`. (#943)
* Significantly improve the performance of `EventLoopFuture.{and,when}AllSucceed`.

* PR improvements.

* Add the fast track for `AllComplete` as well.

* Use `future.inEventLoop` instead of pointer comparison.
2019-04-05 10:56:36 +02: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 46ffd630de
ChannelPipeline: addHandler and removeHandler instead of add/remove (#817)
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
2019-02-21 11:46:54 +00:00
Johannes Weiss 1198931823 ByteBuffer: rename set(<type>:, ...) to set<Type>(...) (#812)
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
2019-02-12 11:11:45 +00:00
Nathan Harris caf9a3d8da standardize `ELF.cascade*` collection of methods (#802)
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:)`
2019-02-05 09:01:48 +00:00
Johannes Weiss c4ff795dda
remove ELP.succeed/fail's labels (#776)
Motivation:

EventLoopPromise.succeed/fail has extraneous labels that don't add
anything but noise.

Modifications:

remove extraneous labels

Result:

less noise in the code
2019-01-24 16:42:53 +00:00
Johannes Weiss 3e7d6a7bfd rename ELF.then to ELF.flatMap (#760)
Motivation:

ELF's API should be as close as possible to the new Result's API.
Therefore, we should rename `then` to `flatMap`

Modifications:

- renamed `then` to `flatMap`
- renamed `thenIfError` to `flatMapError`
- renamed ELF's generic parameter from `T` to `Value`

Result:

- more like Result
- fixes #688
2019-01-21 16:41:04 +00:00
Johannes Weiss 305ee9818b make factory method names start with make (#692)
Motivation:

Swift naming guidelines mandate that factory methods start with `make`,
like `makeSomething`. We had a few that were `newSomething`.

Modifications:

make all factories start with make

Result:

more compliant to Swift naming rules
2018-12-10 17:59:24 +00:00
Johannes Weiss 054f65e473
add String blitting benchmarks (#641)
Motivation:

Writing Strings to ByteBuffers is important, let's have some more
benchmarks.

Modifications:

add String to ByteBuffer benchmarks

Result:

more benchmarks
2018-10-30 23:41:20 -07:00
Norman Maurer 82a6e4d821
Rename numThreads to numberOfThreads parameter. (#443)
Motivation:

We should be consistent with naming and also choose descriptive names.

Modifications:

- Deprecate old init method that uses numThreads
- Add new init with numberOfThreads param name
- Everywhere use the new init

Result:

More consistent and descriptive naming. Fixes https://github.com/apple/swift-nio/issues/432.
2018-05-25 17:37:55 +02:00