From 5dd9f3b6d3f5a62c9cc5fd2aa1606438b7b6e8b4 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 3 Jul 2025 20:30:41 -0400 Subject: [PATCH] Ring loop dispatch --- app/http.php | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/app/http.php b/app/http.php index 30f4013821..05f1c6851d 100644 --- a/app/http.php +++ b/app/http.php @@ -47,6 +47,7 @@ $http = new Server( $payloadSize = 12 * (1024 * 1024); // 12MB - adding slight buffer for headers and other data that might be sent with the payload - update later with valid testing $totalWorkers = intval(System::getEnv('_APP_CPU_NUM', swoole_cpu_num())) * intval(System::getEnv('_APP_WORKER_PER_CORE', 6)); +$nextWorker = new \Swoole\Atomic\Long(0); // lock‑free counter for round‑robin idle‑worker selection /** * Assigns HTTP requests to worker threads by analyzing its payload/content. @@ -66,12 +67,14 @@ $totalWorkers = intval(System::getEnv('_APP_CPU_NUM', swoole_cpu_num())) * intva function dispatch(Server $server, int $fd, int $type, $data = null): int { $resolveWorkerId = function (Server $server, $data = null) { - global $totalWorkers, $domains; + global $totalWorkers, $domains, $nextWorker; + $start = $nextWorker->add(1) % $totalWorkers; // ring‑buffer start index // If data is not set we can send request to any worker // first we try to pick idle worker, if not we randomly pick a worker if ($data === null) { - for ($i = 0; $i < $totalWorkers; $i++) { + for ($offset = 0; $offset < $totalWorkers; $offset++) { + $i = ($start + $offset) % $totalWorkers; if ($server->getWorkerStatus($i) === SWOOLE_WORKER_IDLE) { return $i; } @@ -107,7 +110,8 @@ function dispatch(Server $server, int $fd, int $type, $data = null): int if ($risky) { // If risky request, only consider risky workers - for ($j = $riskyWorkers; $j < $totalWorkers; $j++) { + for ($offset = 0; $offset < ($totalWorkers - $riskyWorkers); $offset++) { + $j = ($start + $riskyWorkers + $offset) % $totalWorkers; /** Reference https://openswoole.com/docs/modules/swoole-server-getWorkerStatus#description */ if ($server->getWorkerStatus($j) === SWOOLE_WORKER_IDLE) { // If idle worker found, give to him @@ -123,7 +127,8 @@ function dispatch(Server $server, int $fd, int $type, $data = null): int // If safe request, give to any idle worker // Its fine to pick risky worker here, because it's idle. Idle is never actually risky - for ($i = 0; $i < $totalWorkers; $i++) { + for ($offset = 0; $offset < $totalWorkers; $offset++) { + $i = ($start + $offset) % $totalWorkers; if ($server->getWorkerStatus($i) === SWOOLE_WORKER_IDLE) { return $i; }