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.
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.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Laravel Tech Community
Specializing in Laravel development, we continuously publish fresh content and grow alongside the elegant, stable Laravel framework.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
