Commit Graph

1749 Commits

Author SHA1 Message Date
Jari (LotU) 198b84b01c Webhooks upgrade complete fix (#1280)
Motivation:

Fixes the bug described in #1279

Modifications:

Moved state change in NIOHTTPClientUpgradeHandler.performUpgrade to after firing buffered messages.

Result:

- The upgradeState will now only change to upgradeComplete after buffered reads are handeld.
- Fixes #1279
2019-12-04 12:04:05 +00:00
Richard Low 1f94a6e620 Out of pipeline byte stream decoding (#1268)
* Add NIOSingleStepByteToMessageDecoder and NIOSingleStepByteToMessageProcessor
for processing byte streams outside of the channel pipeline.

Motivation:

ByteToMessageHandler works well when you can embed it in your pipeline, but if
you have a wrapped protocol (e.g. sending a protocol over HTTP), you can't use
it without losing the context of the outer protocol (e.g. HTTP headers/trailers).

Modifications:

Added NIOSingleStepByteToMessageDecoder and NIOSingleStepByteToMessageProcessor.

Result:

New functionality above.
2019-12-03 11:29:38 +00:00
George Barnett 6d1401ef8e Update Code of Conduct project maintainer (#1278)
Motivation:

The code-of-conduct email address is out-of-date.

Modifications:

Update code-of-conduct email address to swift-server-conduct@group.apple.com

Result:
2019-12-02 12:05:12 +00:00
Johannes Weiss 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
Johannes Weiss 01b40144f2 heap: make checkHeapProperty a tests thing (#1276)
Motivation:

In normal operation, we don't need checkHeapProperty anymore.

Modifications:

Move to tests.

Result:

Less code.
2019-11-29 08:28:38 +00:00
Johannes Weiss cb72048eca don't constantly check the heap property in debug mode (#1272)
Motivation:

So far we've been checking the heap property of our heaps _twice per
heap operation_. I think that's a bit much.

Modifications:

Remove the heap operation checks.

Result:

Runs much faster in debug mode.
2019-11-28 10:33:46 +00:00
Jake 3c879ebbaf Fast atomics (#1263)
Motivation:

The existing Atomic class holds an UnsafeEmbeddedAtomic which holds an OpaquePointer to raw memory for the C atomic. This results in multiple allocations on init. The new NIOAtomic class uses ManagedBufferPointer which tail allocates memory for the C atomic as part of the NIOAtomic class allocation.

Modifications:

Created NIOAtomic class that uses ManagedBufferPointer to allocate memory for the C atomic. Created version of catmc_atomic_* C functions that expect memory to be allocated/deallocated by caller. Created NIOAtomicPrimitive protocol for the new version of catmc_atomic_* functions.

Result:

Purely additive. NIOAtomic is available as a replacement for Atomic which results in fewer memory allocations.
2019-11-28 07:45:05 +00:00
Johannes Weiss abe5219b71
remove random print("hi \(path)") message (#1273) 2019-11-27 21:33:35 +00:00
Johannes Weiss ee0ed3b129
fix a number of memory leaks in the test suite (#1157)
Motivation:

Memory leaks are bad, even in test suites.

Modifications:

Fix a number of memory leaks.

Result:

Fewer leaks.
2019-11-27 19:25:06 +00:00
Cory Benfield b053967abd Support writing WS header to user buffer. (#1168)
Motivation:

In some cases it may be possible to write the (usually small) web socket
frame header to the buffer provided by the user. If we do this we can
avoid an extra pipeline traversal for the small write. This is only
going to be a performance win in cases where we can avoid a
copy-on-write operation on the buffer, but if we can then it's a useful
small win to achieve.

Modifications:

- Refactored the WebSocketFrameEncoder to potentially prepend the frame
    header.
- Added a missing @inlinable attribute.
- Tests.

Result:

Potentially improved performance.
2019-11-27 18:52:03 +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
Johannes Weiss 732a6e0ef4
join the threads of a MultiThreadedEventLoopGroup on shutdown (#1261)
Motivation:

We should join the threads that we spawned which has the extra benefit
of TSan being able to detect our thread leaks.

Modifications:

Join the SelectableEventLoop's thread after it's shut down.

Result:

We join all the threads.
2019-11-27 17:55:50 +00:00
Konrad `ktoso` Malawski 8c0e373bf5 Also collect total bytes allocated in alloc tests (#1116)
Motivation:

It is useful/interesting to have an overview about total bytes
allocated, not only the number of malloc calls.

This is not used to fail tests though, more as an informational thing.

Modifications:

Introduce and hit new counter with allocated size whenever allocations
happen.

Result:

It is possible to inspect the total allocated bytes.
2019-11-27 15:43:19 +00:00
Johannes Weiss c2c725044a
allow deprecated tests to test deprecated functionality (#1271)
Motivation:

It's important to also test deprecated functionliaty. One way of
achieving this without warnings is to also deprecate the tests that test
this deprecated functionality. Unfortunately, on Linux we need to
generate lists of tests which would then reference deprecated tests
(which gives us a warning).

Modifications:

Deprecate test suites and the main test runner all the way to the top so
never get warnings.

Result:

Possible to test deprecated functionlity without warnings.
2019-11-27 14:26:51 +00:00
George Barnett 302dee3e1a Make ByteBufferView mutable (#1208)
Motivation:

ByteBufferView isn't a mutable collection, but it probably should be.

Modifications:

- Add `copyBytes(at:to:length)` to `ByteBuffer` to copy bytes from a
  readable region of a buffer to another part of the buffer
- Conform `ByteBufferView` to `MutableCollection`, `RangeReplaceableCollection`
  and `MutableDataProtocol`
- Add an allocation counting test

Result:

`ByteBufferView` is now mutable.
2019-11-27 10:25:15 +00:00
Konrad `ktoso` Malawski 7d8e6b2323 Fix typo in Endianness docs (#1269)
Fix typo in Endianness docs

Motivation:

Slight typo in docs of Endianness

Modifications:

`significat` -> `significant`

Result:

Less typos, happier users.
2019-11-26 16:59:49 +00:00
Cory Benfield 5a7b23d8b5
Fix Dash docset generation. (#1256)
Motivation:

Jazzy generates Dash docsets for us, but currently they don't work. This
is because the URLs they generate aren't matching the URL scheme we
have. That makes them next to useless.

Modifications:

Add a trailing '/' to the root URL.

Result:

Calls to Ruby's URI.join won't blow away the final path component in the
root URL, which means that the docsets will have correct URLs going
forward.
2019-11-20 13:41:02 +00:00
Johannes Weiss d269ed5a26 don't use `public extension` (#1259)
Motivation:

`public extension`s are very dangerous because the make it so easy to
slip in public API by accident.

Modifications:

Don't use `public extension`.

Result:

Fewer chances to accidentally make stuff public.
2019-11-20 13:26:00 +00:00
Johannes Weiss 67e173df25
remove internal ExpressibleBy(Integer|Array)Literal conformances (#1258)
Motivation:

The ExpressibleBy*Literal conformances require `@usableFromInline` inits
which make it harder to make NIO compatible with library evolution
because we can no longer just remove all `@inlinable`s and call it a
day.

Modifications:

Remove the ExpressibleBy*Literal conformances for internal types.

Result:

NIO easy to convert into a library evolution mode.
2019-11-20 11:55:12 +01:00
Pushparaj Zala 86f41d8d40 Added parentheses in TimeAmount constructors to generate optimal code. As Per issue #1249 (#1250)
Motivation:

For better codegen for TimeAmount struct.
After this change overflow will not be checked at each multiplication stage.

Modifications:

- Added parentheses in static constructors of `TimeAmount`

Result:

No change logically except better codegen
2019-11-18 16:10:34 +01:00
Johannes Weiss 9dd9f36bfd
make-single-file-spm: support lines ending in `n` (#1251)
Motivation:

make-single-file-spm has a weird bug where it would chop off trailing
`n` characters in all lines due to a badly set `IFS` bash variable.

Modifications:

Set `IFS=""` which is correct.

Result:

make-single-file-spm will not chop off trailing `n`s.
2019-11-18 15:24:18 +01:00
George Barnett ff01888051
Fix running run-nio-alloc-counter-tests.sh for a single test (#1245)
Motivation:

Using the single test argument with the run-nio-alloc-counter-tests.sh
does not work as expected as the given test would just replace the first
test in the list.

Modifications:

Replace the tests to run with a single-element array containing the test
provided as an argument.

Result:

- A single test can be run when specified as a command line arg.
2019-11-14 10:44:40 +00:00
Johannes Weiss 746fb8440f HTTP1TestServer: close accepted channel on `stop` (#1246)
Motivation:

The HTTP1TestServer forgot to actually close the accepted channel on
`stop`.

Modifications:

Close the accepted Channel on stop.

Result:

Fewer bugs.
2019-11-14 09:49:44 +00:00
Johannes Weiss d36864ef10
fix new warnings about empty OptionSets (#1238)
Motivation:

Very new Swift compilers warn about generating empty OptionSets when
using `rawValue: 0`.

Modifications:

Replace the deliberately empty OptionSets by `[]`.

Result:

No warnings.
2019-11-13 19:44:15 +00:00
Johannes Weiss 1ca4c2113c
perf tests: switch printed metric to mean (#1244)
Motivation:

We should print the same metric that we compare with.

Modifications:

Switch the printed metric to the one selected in `::METRIC`.

Result:

More correct printouts.
2019-11-13 19:07:50 +00:00
Johannes Weiss 0fe0ceca11 fix two potential hangs in the test suite (#1240)
Motivation:

There were at least 2 tests in our test suite that were racing EventLoop
shutdown.

Modifications:

Don't race EL shutdown.

Result:

More reliable test suite.
2019-11-13 14:14:15 +00:00
Johannes Weiss 1c160afa95
add make-single-file-spm (#1236)
Motivation:

make-single-file-spm is a simple bash script that can turn a single file
into a SwiftPM project with multiple modules (all defined in a single
file with special markers such as `// MODULE: Foo`. This is mostly
useful for performance evaluation of Swift becuase in almost all cases,
you'll need multiple modules which is quite a bit of work to set up.

Modifications:

Add make-single-file-spm

Result:

More useful scripts in the NIO repo.
2019-11-12 19:07:01 +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
Johannes Weiss 578e6d4bef
don't use variable initialisation outside of `init` (#1235)
Motivation:

The Swift compiler actively tries to make our live hard and puts all
initialisations of variables that are initialised using the shorthand
syntax

    @usableFromInline var myVar: MyVarType = .init()

into a _non-inlinable_ function

     variable initialization expression of MyModule.MyType.myVar : MyVarType

This means that the following pattern

    public struct MyType {
        @usableFromInline var myVar: MyVarType = .init()

        @inlinable public init() {
        }
    }

leads to code for the `init` that looks like

    CALL variable_initialization_expression_...

instead of also inlining the the code for the variable initialiser.

Modifications:

Don't use `@usableFromInline var myVar: MyVarType = ...` anywhere,
instead put it explicitly into the @inlinable `init`s which makes
actually inlinable.
I even removed that syntax from places where it doesn't matter
(eg. non-@inlinable inits) for consistency and in case someone were to
make the init inlinable later.

Result:

Minor performance wins working around https://bugs.swift.org/browse/SR-11768
2019-11-12 15:11:32 +00:00
Richard Low d4a18c58df Disallow zero EventLoop threads (#1230)
Motivation:

Zero EventLoop threads makes no sense and leads to a crash (see #1223)

Modifications:

Add a precondition

Result:

Initializing EventLoop with zero threads will fail precondition rather than crash later.
2019-11-12 14:27: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
Richard Low 51640a3104 Update ByteBuffer docs to advance write index on set operations (#1233)
Motivation:

Docs give unexpected results since behavior was changed in NIO 2
to only see readable bytes. Fixes #1232.

Modifications:

Documentation updated.

Result:

Documentation gives expected results with no errors.
2019-11-11 12:12:23 +00:00
Johannes Weiss 93de65a217 cleanup some unnecessary #if os (#1199)
Motivation:

Certain `#if os` uses in SwiftNIO are unnecessary, they should be
removed.

Modifications:

Removed unnecessary `#if os` in SwiftNIO.

Result:

Nicer codebase.
2019-11-11 11:36:37 +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
Johannes Weiss 23d546e1fc EventLoopFuture: save one allocation per future (#1224)
Motivation:

Every EventLoopFuture was allocating an atomic boolean (which needs to
heap allocate because Swift) literally just to make the leakage checker
work. But the leakage checker is only active in debug mode, the
allocation however was _always_ done.

Modifications:

Remove the allocation in release mode (by making the atomic optional).

Result:

Fewer allocations
2019-11-11 09:48:36 +00:00
Johannes Weiss e572cf42c4
ByteBuffer: readJSONDecodable: use specified decoder (#1228)
Motivation:

ByteBuffer.readJSONDecodable just ignored the JSONDecoder that got
passed in.

Modifications:

Pass through the JSONDecoder that was specified.

Result:

Respect the user's choices.
2019-11-09 17:06:57 +00:00
Johannes Weiss a4b9a2816a
update contributors (#1225) 2019-11-08 22:08:37 +00:00
Marli Oshlack e4356bd005 Cow-box WebSocketFrame. (#1211)
Motivation:

WebSocketFrameDecoder makes an allocation due to WebSocketFrame not fitting in an
existential. We should reduce this overhead.

Modifications:

Moved data and extensionData into a cow-box and reorder fields to more efficiently
pack them.

Result:

WebSocketFrame is now 14 bytes, down from 55.
2019-11-08 12:27:06 +00:00
Marli Oshlack bc661cbb77 Allow single test to be specified as an argument to run-nio-alloc-counter-tests.sh. (#1214)
* Allow single test to be specified as an argument to run-nio-alloc-counter-tests.sh.

Motivation:

run-nio-alloc-counter-tests.sh currently runs all tests. When writing or
debugging a test, you commonly want to run a single test. At the moment the
common practice is to edit the script to hardcode a test to run, which is
annoying and error-prone.

Modifications:

Add an optional argument to the script to specify the test to run.

Result:

$ ./run-nio-alloc-counter-tests.sh

runs all tests.

$ ./run-nio-alloc-counter-tests.sh test_decode_1000_ws_frames.swift

runs only test_decode_1000_ws_frames.swift.
2019-11-07 11:05:16 +00:00
Gwynne Raskind 1a9a543b6b Use self as the decoder when decoding a ByteBuffer (#1221)
Motivation:

JSONDecoder settings should be respected but were not.

Modifications:

This allows actually configuring the `JSONDecoder` instead of being stuck with the defaults.

Result:

Settings respected.
2019-11-06 16:08:31 +00:00
Cory Benfield fbe0c8a6b8 Add inlinability to ByteBuffer getters. (#1220)
Motivation:

In complex ByteBuffer parsing code a surprising amount of cost comes
from retain/release operations that are emitted by the compiler around
calls to readerIndex/writerIndex, readableBytes/writableBytes, and
ByteBufferSlice._lowerBound. These are all straightforward computed
properties based on usableFromInline operations, and so they can be made
inlinable.

Modifications:

Joannis' sample benchmark runtime is halved by eliminating
retains/releases.

Result:

Better, faster parsing code.
2019-11-04 19:31:26 +01:00
Christian Weinberger a0ab329d9d Add an option to ByteBuffer.clear() to specify minimumCapacity (#1204) 2019-10-31 21:19:24 +01:00
Heidi Puk Hermann bad79c584e Add function preconditionIsNotBlacklistedErrno (#1201)
Motivation:

Certain POSIX error numbers mean the NIO program is broken beyond repair and should crash. One such value is EBADF, which indicates that the file descriptor that NIO passed to the kernel is invalid for some reason. SR-11557 was discovered in part because debug builds of NIO crash for this.
I have promoted these checks from an assertion to a precondition adding a function preconditionIsNotBlacklistedErrno. Issue was raised in issue #1156

Modifications:

- Add function preconditionIsNotBlacklistedErrno to enable option to stop program execution in both debug mode and release mode if the errno is blacklisted.
- Update assertIsNotBlacklistedErrno to all preconditionIsNotBlacklistedErrno when the program is in debug mode
- Update wrapSyscallMayBlock, wrapSyscall, wrapErrorIsNullReturnCall, and close to call preconditionIsNotBlacklistedErrno in stead of assertIsNotBlacklistedErrno

Result:

Functions wrapSyscallMayBlock, wrapSyscall, wrapErrorIsNullReturnCall, and close will stop the execution in both debug mode and release mode if the errno is blacklisted.
2019-10-31 13:10:00 +01:00
Kamil Borzym 62fd8729d3 `ByteBuffer.clear` should reset the `ByteBuffer._slice`. (#1212)
Motivation:

ByteBuffer.clear doesn't reset the ByteBuffer._slice. Imagine having a byte buffer slice (ByteBuffer.getSlice). Calling ByteBuffer.clear on the slice will reset the reader and writer, but the ByteBuffer.capacity will return the old slice size, not the full storage capacity. After this change ByteBuffer.clear will also reset the ByteBuffer._slice to regain the whole ByteBuffer._storage.

Modifications:

Just setting the full storage slice in the ByteBuffer.clear method.

Result:

After that change ByteBuffer.clear will reset byte buffer slice to full capacity of underlying storage.
2019-10-31 09:05:51 +01:00
Marli Oshlack 05616c5119 Added an allocation benchmark for WebSocketFrameDecoder. (#1210) 2019-10-30 17:41:20 +01:00
David Evans c83a4317f3 Fix typo (#1206) 2019-10-30 14:16:46 +01: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
Siemen Sikkema 6ac4cd5a21 Make SocketAddress.port mutable (#1200)
* Make SocketAddress.port mutable

* Add linux test

* Precondition for setting non-nil port to unix socket

* Update Sources/NIO/SocketAddresses.swift

Co-Authored-By: George Barnett <gbrntt@gmail.com>
2019-10-30 12:53:06 +01:00
Johannes Weiss 22073b97be add socketpair to the POSIX wrappers (#1198)
Motivation:

For some reason, we never added `socketpair` to the POSIX wrappers but
it should be there.

Modifications:

Add socketpair to the POSIX wrappers and make use of it.

Result:

Nicer code base.
2019-10-30 08:01:42 +00:00