Unlocking Swoole 4 Coroutines: High‑Performance PHP I/O and Network Demo

This article demonstrates how Swoole 4’s new coroutine kernel enables fully synchronous‑style PHP code to perform asynchronous I/O, file operations, database queries, and TCP/UDP networking within a single process, showcasing massive performance gains through practical code examples.

Laravel Tech Community
Laravel Tech Community
Laravel Tech Community
Unlocking Swoole 4 Coroutines: High‑Performance PHP I/O and Network Demo

Swoole 4 introduces a brand‑new coroutine kernel that, together with a dedicated development team, marks an unprecedented era for PHP performance optimization.

Versions 4 and above embed high‑availability coroutines, allowing developers to write asynchronous I/O code using ordinary synchronous PHP syntax without any special keywords; the runtime automatically schedules the coroutines.

The example below enables the coroutine runtime, then runs a series of concurrent tasks inside Co\run. After enabling Swoole\Runtime::enableCoroutine(), operations such as sleep, file I/O, PDO/MySQLi queries, and stream handling become non‑blocking.

// Enable coroutine for built‑in I/O functions
Swoole\Runtime::enableCoroutine();
$s = microtime(true);
Co\run(function () {
    // 10k sleep operations
    for ($c = 100; $c--;) {
        go(function () {
            for ($n = 100; $n--;) {
                usleep(1000);
            }
        });
    }

    // 10k file read/write
    for ($c = 100; $c--;) {
        go(function () use ($c) {
            $tmp = "/tmp/test-{$c}.php";
            for ($n = 100; $n--;) {
                $self = file_get_contents(__FILE__);
                file_put_contents($tmp, $self);
                assert(file_get_contents($tmp) === $self);
            }
            unlink($tmp);
        });
    }

    // 10k PDO queries
    for ($c = 50; $c--;) {
        go(function () {
            $pdo = new PDO('mysql:host=127.0.0.1;dbname=test;charset=utf8', 'root', 'root');
            $stmt = $pdo->prepare('SELECT * FROM `user`');
            for ($n = 100; $n--;) {
                $stmt->execute();
                assert(count($stmt->fetchAll()) > 0);
            }
        });
    }

    // 10k MySQLi queries
    for ($c = 50; $c--;) {
        go(function () {
            $mysqli = new Mysqli('127.0.0.1', 'root', 'root', 'test');
            $stmt = $mysqli->prepare('SELECT `id` FROM `user`');
            for ($n = 100; $n--;) {
                $stmt->bind_result($id);
                $stmt->execute();
                $stmt->fetch();
                assert($id > 0);
            }
        });
    }

    // TCP server & client (12.8k requests in one process)
    function tcp_pack(string $data): string { return pack('n', strlen($data)) . $data; }
    function tcp_length(string $head): int { return unpack('n', $head)[1]; }
    go(function () {
        $ctx = stream_context_create(['socket' => ['so_reuseaddr' => true, 'backlog' => 128]]);
        $socket = stream_socket_server('tcp://0.0.0.0:9502', $errno, $errstr, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $ctx);
        if (!$socket) { echo "$errstr ($errno)
"; return; }
        $i = 0;
        while ($conn = stream_socket_accept($socket, 1)) {
            stream_set_timeout($conn, 5);
            for ($n = 100; $n--;) {
                $data = fread($conn, tcp_length(fread($conn, 2)));
                assert($data === "Hello Swoole Server #{$n}!");
                fwrite($conn, tcp_pack("Hello Swoole Client #{$n}!"));
            }
            if (++$i === 128) { fclose($socket); break; }
        }
    });
    for ($c = 128; $c--;) {
        go(function () {
            $fp = stream_socket_client('tcp://127.0.0.1:9502', $errno, $errstr, 1);
            if (!$fp) { echo "$errstr ($errno)
"; return; }
            stream_set_timeout($fp, 5);
            for ($n = 100; $n--;) {
                fwrite($fp, tcp_pack("Hello Swoole Server #{$n}!"));
                $data = fread($fp, tcp_length(fread($fp, 2)));
                assert($data === "Hello Swoole Client #{$n}!");
            }
            fclose($fp);
        });
    }

    // UDP server & client (12.8k requests in one process)
    go(function () {
        $socket = new Swoole\Coroutine\Socket(AF_INET, SOCK_DGRAM, 0);
        $socket->bind('127.0.0.1', 9503);
        $clientMap = [];
        for ($c = 128; $c--;) {
            for ($n = 0; $n < 100; $n++) {
                $recv = $socket->recvfrom($peer);
                $uid = "{$peer['address']}:{$peer['port']}";
                $id = $clientMap[$uid] = ($clientMap[$uid] ?? -1) + 1;
                assert($recv === "Client: Hello #{$id}!");
                $socket->sendto($peer['address'], $peer['port'], "Server: Hello #{$id}!");
            }
        }
        $socket->close();
    });
    for ($c = 128; $c--;) {
        go(function () {
            $fp = stream_socket_client('udp://127.0.0.1:9503', $errno, $errstr, 1);
            if (!$fp) { echo "$errstr ($errno)
"; return; }
            for ($n = 0; $n < 100; $n++) {
                fwrite($fp, "Client: Hello #{$n}!");
                $recv = fread($fp, 1024);
                list($address, $port) = explode(':', stream_socket_get_name($fp, true));
                assert($address === '127.0.0.1' && (int)$port === 9503);
                assert($recv === "Server: Hello #{$n}!");
            }
            fclose($fp);
        });
    }
});

echo 'use ' . (microtime(true) - $s) . ' s';

The script runs all the above coroutines concurrently in a single PHP process, achieving tens of thousands of I/O operations, database queries, and network exchanges without blocking, and finally prints the total execution time.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

performanceTCPPHPcoroutineUDPSwooleAsync IO
Laravel Tech Community
Written by

Laravel Tech Community

Specializing in Laravel development, we continuously publish fresh content and grow alongside the elegant, stable Laravel framework.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.