Commit Graph

14 Commits

Author SHA1 Message Date
ser 6213ba7a06
Pooled control message storage. (#2422) 2023-05-31 06:06:23 -07:00
ser 8193940b9a
Buffer pool for message headers and addresses. (#2378)
* Pool buffers for messages and addresses.

* Revert changes related to controlMessageStorage

* Cosmetic fix.

---------

Co-authored-by: Cory Benfield <lukasa@apple.com>
2023-03-10 16:06:02 +00:00
Cory Benfield 9afaf801e5
Don't retain a task when all we want is a time (#2373)
Motivation:

To know when we next need to wake up, we keep track of what the next
deadline will be. This works great, but in order to keep track of this
UInt64 we save off an entire ScheduledTask. This object is quite wide (6
pointers wide), and two of those pointers require ARC traffic, so doing
this saving produces unnecessary overhead.

Worse, saving this task plays poorly with task cancellation. If the
saved task is cancelled, this has the effect of "retaining" that task
until the next event loop tick. This is unlikely to produce catastrophic
bugs in real programs, where the loop does tick, but it violates our
tests which rigorously assume that we will always drop a task when it is
cancelled. In specific manufactured cases it's possible to produce leaks
of non-trivial duration.

Modifications:

- Wrote a weirdly complex test.
- Moved the implementation of Task.readyIn to a method on NIODeadline
- Saved a NIODeadline instead of a ScheduledTask

Result:

Minor performance improvement in the core event loop processing, minor
correctness improvement.
2023-02-20 07:27:58 -08:00
Cory Benfield 39047aec7c
Make PooledBuffer safer. (#2363)
Motivation:

PooledBuffer is an inherently unsafe type, but its original incarnation
was less safe than it needed to be. In particular, we can rewrite it to
ensure that it is compatible with automatic reference counting.

Modifications:

- Rewrite PooledBuffer to use ManagedBuffer
- Clean up alignment math
- Use scoped accessors
- Add hooks for future non-scoped access

Result:

Safer, clearer code
2023-02-08 07:59:17 +00:00
ser 1e7ad9a0db
Pool buffers for ivecs and storage refs in the event loop. (#2358)
* Pool buffers for ivecs and storage refs in the event loop.

* Introduce PoolElement for poolable objects and add some bounds checks for the pooled buffers.

* Some polishes.

* Fix build failure with Swift 5.5/5.6

* User raw pointers instead of typed.
2023-02-07 13:48:26 +00:00
thomas-gill-0xff b201ff561d
Remove useless instance variables in the SelectableEventLoop (#2338)
Motivation:

Less code we have - less bugs we have.
The fix remove few lines of code keeping the same functionality.

Modifications:

Just remove some useless instance variables.

Result:

Less code.
2022-12-21 03:41:44 -08:00
Johannes Weiss 4ed8e1e228
rename class Lock to struct NIOLock (#2266) 2022-09-21 07:36:42 -07:00
YR Chen a501353ef6
Deprecate `NIOAtomics` in favor of `Atomics` (#2204)
Co-authored-by: Cory Benfield <lukasa@apple.com>
2022-07-01 02:31:14 -07:00
Si Beaumont 69bb75df32
Throw fatalError when scheduling on shutdown EL if SWIFTNIO_STRICT is set (#2190)
* Throw fatalError when scheduling on shutdown EL if SWIFTNIO_STRICT is set

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

* Add CrashTest for SWIFTNIO_STRICT crash

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

* fixup: Extract env var parsing to static let

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

Co-authored-by: Cory Benfield <lukasa@apple.com>
2022-06-14 05:43:48 -07: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
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
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 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