diff --git a/html/input.php b/html/input.php index 460d464..6fb6c60 100644 --- a/html/input.php +++ b/html/input.php @@ -7,6 +7,7 @@ if (!file_exists($coreFile)) { file_put_contents($coreFile, json_encode([])); } +/* Get NUMA topology with PHYSICAL cores only */ function getNumaTopology(): array { $out = shell_exec("numactl --hardware"); @@ -17,47 +18,53 @@ function getNumaTopology(): array $node = (int)$m[1]; $cpus = array_map('intval', preg_split('/\s+/', trim($m[2]))); - /* use EVEN CPUs only: 0,2,4,... */ - $nodes[$node] = array_values( - array_filter($cpus, fn($c) => $c % 2 === 0) - ); + // keep even CPUs only (physical cores) + $cpus = array_values(array_filter($cpus, fn($c) => $c % 2 === 0)); + + $nodes[$node] = $cpus; } } - ksort($nodes); // ensure deterministic order + ksort($nodes); return $nodes; } -/* Allocate core in strict round-robin */ +/* Allocate core: core-index first, node second */ function allocateCore(int $serviceId): array { global $coreFile; - $map = json_decode(file_get_contents($coreFile), true) ?: []; + $map = json_decode(file_get_contents($coreFile), true) ?: []; $nodes = getNumaTopology(); $nodeIds = array_keys($nodes); - $nodeCount = count($nodeIds); // ✅ calculated BEFORE processing + $nodeCount = count($nodeIds); if ($nodeCount === 0) { return ["node" => 0, "cpu" => 0]; } + // total services already allocated $index = count($map); - /* Round-robin node selection */ - $nodePos = $index % $nodeCount; - $node = $nodeIds[$nodePos]; + /* + * ROUND-ROBIN MATH (IMPORTANT) + * + * coreIndex = floor(index / nodeCount) + * nodeIndex = index % nodeCount + */ + $coreIndex = intdiv($index, $nodeCount); + $nodeIndex = $index % $nodeCount; - /* Per-node CPU index */ - $cpuIndex = intdiv($index, $nodeCount); + $node = $nodeIds[$nodeIndex]; - /* Wrap safely if CPUs exhausted */ - if (!isset($nodes[$node][$cpuIndex])) { - $cpuIndex = $cpuIndex % count($nodes[$node]); + // wrap core index safely if cores exhausted + $coreCount = count($nodes[$node]); + if ($coreCount === 0) { + return ["node" => $node, "cpu" => 0]; } - $cpu = $nodes[$node][$cpuIndex]; + $cpu = $nodes[$node][$coreIndex % $coreCount]; $map[$serviceId] = [ "node" => $node, @@ -88,43 +95,6 @@ function getServiceCore(int $serviceId): ?array return $map[$serviceId] ?? null; } -$jsonFile = __DIR__ . "/input.json"; -if (!file_exists($jsonFile)) { - file_put_contents($jsonFile, json_encode([])); -} -$data = json_decode(file_get_contents($jsonFile), true); - -/* Fix old entries missing service_name or volume */ -foreach ($data as $k => $d) { - if (!isset($d["service_name"])) $data[$k]["service_name"] = ""; - if (!isset($d["volume"])) $data[$k]["volume"] = "0"; -} -file_put_contents($jsonFile, json_encode($data, JSON_PRETTY_PRINT)); - -/* ---------------- ADD NEW ---------------- */ -if ($_SERVER["REQUEST_METHOD"] === "POST" && $_POST["action"] === "add") { - - $new = [ - "id" => time(), - "service_name" => $_POST["service_name"], - "input_udp" => $_POST["input_udp"], - "output_udp" => $_POST["output_udp"], - "video_format" => $_POST["video_format"], - "audio_format" => $_POST["audio_format"], - "resolution" => $_POST["resolution"], - "video_bitrate" => $_POST["video_bitrate"], - "audio_bitrate" => $_POST["audio_bitrate"], - "volume" => $_POST["volume"], - "service" => $_POST["service"] - ]; - - $data[] = $new; - file_put_contents($jsonFile, json_encode($data, JSON_PRETTY_PRINT)); - - $alloc = getServiceCore($id); - if ($alloc === null) { - $alloc = allocateCore($id); - } $core = (int)$alloc["cpu"]; $node = (int)$alloc["node"];