Repository: apple/swift-nio
File: Sources/NIOPerformanceTester/TCPThroughputBenchmark.swift (Swift)

Code before:

        let connectionEstablishedPromise: EventLoopPromise<EventLoop> = self.group.next().makePromise()

        let promise = self.group.next().makePromise(of: NIOLoopBound<ServerHandler>.self)
        self.serverChannel = try ServerBootstrap(group: self.group)
            .childChannelInitializer { channel in
                channel.eventLoop.makeCompletedFuture {
                    let serverHandler = ServerHandler(connectionEstablishedPromise, eventLoop: channel.eventLoop)
                    promise.succeed(NIOLoopBound(serverHandler, eventLoop: channel.eventLoop))
                    try channel.pipeline.syncOperations.addHandler(serverHandler)
                }
            }
            .bind(host: "127.0.0.1", port: 0)
            .wait()

        self.serverHandler = try promise.futureResult.wait()

        self.clientChannel = try ClientBootstrap(group: group)
            .channelInitializer { channel in
                channel.eventLoop.makeCompletedFuture {
                    try channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(StreamDecoder()))
                    try channel.pipeline.syncOperations.addHandler(ClientHandler())
                }
            }
            .connect(to: serverChannel.localAddress!)
            .wait()

        var message = self.serverChannel.allocator.buffer(capacity: self.messageSize)
        message.writeInteger(UInt16(messageSize), as: UInt16.self)
        for idx in 0..<(self.messageSize - MemoryLayout<UInt16>.stride) {
            message.writeInteger(UInt8(truncatingIfNeeded: idx), endianness: .little, as: UInt8.self)
        }
        self.message = message

        self.serverEventLoop = try connectionEstablishedPromise.futureResult.wait()
    }

    func tearDown() {
        try! self.clientChannel.close().wait()
        try! self.serverChannel.close().wait()
        try! self.group.syncShutdownGracefully()
    }

    func run() throws -> Int {
        let isDonePromise = self.clientChannel.eventLoop.makePromise(of: Void.self)
        let clientChannel = self.clientChannel!
        let expectedMessages = self.messages

        try clientChannel.eventLoop.submit {
            try clientChannel.pipeline.syncOperations.handler(type: ClientHandler.self).prepareRun(
                expectedMessages: expectedMessages,

Review comment (bug):
without this change, this is a guaranteed deadlock. The server `childChannelInitializer` can't run before the client starts connecting.

Code after:

        let connectionEstablishedPromise: EventLoopPromise<EventLoop> = self.group.next().makePromise()

        let promise = self.group.next().makePromise(of: NIOLoopBound<ServerHandler>.self)
        self.serverChannel = try ServerBootstrap(group: self.group)
            .childChannelInitializer { channel in
                channel.eventLoop.makeCompletedFuture {
                    let serverHandler = ServerHandler(connectionEstablishedPromise, eventLoop: channel.eventLoop)
                    promise.succeed(NIOLoopBound(serverHandler, eventLoop: channel.eventLoop))
                    try channel.pipeline.syncOperations.addHandler(serverHandler)
                }
            }
            .bind(host: "127.0.0.1", port: 0)
            .wait()

        self.clientChannel = try ClientBootstrap(group: group)
            .channelInitializer { channel in
                channel.eventLoop.makeCompletedFuture {
                    try channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(StreamDecoder()))
                    try channel.pipeline.syncOperations.addHandler(ClientHandler())
                }
            }
            .connect(to: serverChannel.localAddress!)
            .wait()

        self.serverHandler = try promise.futureResult.wait()

        var message = self.serverChannel.allocator.buffer(capacity: self.messageSize)
        message.writeInteger(UInt16(messageSize), as: UInt16.self)
        for idx in 0..<(self.messageSize - MemoryLayout<UInt16>.stride) {
            message.writeInteger(UInt8(truncatingIfNeeded: idx), endianness: .little, as: UInt8.self)
        }
        self.message = message

        self.serverEventLoop = try connectionEstablishedPromise.futureResult.wait()
    }

    func tearDown() {
        try! self.clientChannel.close().wait()
        try! self.serverChannel.close().wait()
        try! self.group.syncShutdownGracefully()
    }

    func run() throws -> Int {
        let isDonePromise = self.clientChannel.eventLoop.makePromise(of: Void.self)
        let clientChannel = self.clientChannel!
        let expectedMessages = self.messages

        try clientChannel.eventLoop.submit {
            try clientChannel.pipeline.syncOperations.handler(type: ClientHandler.self).prepareRun(
                expectedMessages: expectedMessages,