Open fabianfett opened 1 month ago
Can we also add another benchmark for the NIOAsyncChannel
that uses the task executor next to the global executor hook to prove that this indeed does what we want it to do.
Performance results on my machine:
==================
NIOPosixBenchmarks
==================
TCPEcho pure NIO 1M times
╒═════════════════════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╕
│ Metric │ p0 │ p25 │ p50 │ p75 │ p90 │ p99 │ p100 │ Samples │
╞═════════════════════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╡
│ Context switches │ 4370 │ 4370 │ 4370 │ 4370 │ 4370 │ 4370 │ 4370 │ 1 │
├─────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
│ Malloc (total) * │ 428 │ 428 │ 428 │ 428 │ 428 │ 428 │ 428 │ 1 │
├─────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
│ Time (total CPU) (ms) * │ 4537 │ 4537 │ 4537 │ 4537 │ 4537 │ 4537 │ 4537 │ 1 │
╘═════════════════════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╛
TCPEchoAsyncChannel pure async/await 1M times
╒═════════════════════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╕
│ Metric │ p0 │ p25 │ p50 │ p75 │ p90 │ p99 │ p100 │ Samples │
╞═════════════════════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╡
│ Context switches (K) │ 148 │ 148 │ 148 │ 148 │ 148 │ 148 │ 148 │ 1 │
├─────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
│ Malloc (total) (K) * │ 1492 │ 1492 │ 1492 │ 1492 │ 1492 │ 1492 │ 1492 │ 1 │
├─────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
│ Time (total CPU) (ms) * │ 8431 │ 8431 │ 8431 │ 8431 │ 8431 │ 8431 │ 8431 │ 1 │
╘═════════════════════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╛
TCPEchoAsyncChannel using globalHook 1M times
╒═════════════════════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╕
│ Metric │ p0 │ p25 │ p50 │ p75 │ p90 │ p99 │ p100 │ Samples │
╞═════════════════════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╡
│ Context switches │ 9498 │ 9498 │ 9498 │ 9498 │ 9498 │ 9498 │ 9498 │ 1 │
├─────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
│ Malloc (total) (K) * │ 221 │ 221 │ 221 │ 221 │ 221 │ 221 │ 221 │ 1 │
├─────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
│ Time (total CPU) (ms) * │ 9011 │ 9011 │ 9011 │ 9011 │ 9011 │ 9011 │ 9011 │ 1 │
╘═════════════════════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╛
TCPEchoAsyncChannel using task executor preference 1M times
╒═════════════════════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╕
│ Metric │ p0 │ p25 │ p50 │ p75 │ p90 │ p99 │ p100 │ Samples │
╞═════════════════════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╡
│ Context switches │ 8352 │ 8352 │ 8352 │ 8352 │ 8352 │ 8352 │ 8352 │ 1 │
├─────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
│ Malloc (total) (K) * │ 6175 │ 6175 │ 6175 │ 6175 │ 6175 │ 6175 │ 6175 │ 1 │
├─────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
│ Time (total CPU) (ms) * │ 9336 │ 9336 │ 9336 │ 9336 │ 9336 │ 9336 │ 9336 │ 1 │
╘═════════════════════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╛
Add TaskExecutor conformance to EventLoops
Motivation
Swift 6 introduces the option to supply your own task executors to the Swift concurrency runtime (SE-0417). SwiftNIO's EventLoop should conform to the new TaskExecutor protocol to support running Swift concurrency Tasks on it. This will allow fewer context switches in Swift on server applications.
Modifications
SerialExecutor
)NIODefaultSerialEventLoopExecutor
toNIODefaultEventLoopExecutor
NIODefaultEventLoopExecutor
now also implementsTaskExecutor
protocolNIOTaskEventLoopExecutor
protocol that makes it easy for adopters to get a better implementationResult
Adopters can use ELs as task executors