This commit is contained in:
devdatt 2026-01-18 14:28:09 +05:30
parent e703fcc068
commit 61aa7782c3
1 changed files with 63 additions and 64 deletions

View File

@ -7,7 +7,7 @@ if (!file_exists($coreFile)) {
file_put_contents($coreFile, json_encode([])); file_put_contents($coreFile, json_encode([]));
} }
/* Read NUMA topology */ /* ---------- STEP 1: READ & COUNT NUMA TOPOLOGY ---------- */
function getNumaTopology(): array function getNumaTopology(): array
{ {
$out = shell_exec("numactl --hardware"); $out = shell_exec("numactl --hardware");
@ -18,7 +18,12 @@ function getNumaTopology(): array
$node = (int)$m[1]; $node = (int)$m[1];
$cpus = array_map('intval', preg_split('/\s+/', trim($m[2]))); $cpus = array_map('intval', preg_split('/\s+/', trim($m[2])));
sort($cpus); sort($cpus);
$nodes[$node] = $cpus;
$nodes[$node] = [
"all" => $cpus,
"even" => array_values(array_filter($cpus, fn($c) => $c % 2 === 0)),
"odd" => array_values(array_filter($cpus, fn($c) => $c % 2 === 1)),
];
} }
} }
@ -26,82 +31,77 @@ function getNumaTopology(): array
return $nodes; return $nodes;
} }
/* Allocate core with EVEN-first, ODD-later, safe round robin */ /* ---------- STEP 2: BUILD GLOBAL ROUND-ROBIN PLAN ---------- */
function buildAllocationPlan(array $nodes): array
{
$plan = [];
$nodeIds = array_keys($nodes);
$nodeCount = count($nodeIds);
if ($nodeCount === 0) {
return $plan;
}
/* EVEN cores first (physical cores) */
$maxEven = 0;
foreach ($nodes as $n) {
$maxEven = max($maxEven, count($n["even"]));
}
for ($coreIndex = 0; $coreIndex < $maxEven; $coreIndex++) {
foreach ($nodeIds as $node) {
if (isset($nodes[$node]["even"][$coreIndex])) {
$plan[] = [
"node" => $node,
"cpu" => $nodes[$node]["even"][$coreIndex]
];
}
}
}
/* ODD cores next (hyper-threads) */
$maxOdd = 0;
foreach ($nodes as $n) {
$maxOdd = max($maxOdd, count($n["odd"]));
}
for ($coreIndex = 0; $coreIndex < $maxOdd; $coreIndex++) {
foreach ($nodeIds as $node) {
if (isset($nodes[$node]["odd"][$coreIndex])) {
$plan[] = [
"node" => $node,
"cpu" => $nodes[$node]["odd"][$coreIndex]
];
}
}
}
return $plan;
}
/* ---------- STEP 3: ALLOCATE USING PRECOMPUTED PLAN ---------- */
function allocateCore(int $serviceId): array function allocateCore(int $serviceId): array
{ {
global $coreFile; global $coreFile;
$map = json_decode(file_get_contents($coreFile), true) ?: []; $map = json_decode(file_get_contents($coreFile), true) ?: [];
$nodes = getNumaTopology(); $nodes = getNumaTopology();
$plan = buildAllocationPlan($nodes);
if (empty($nodes)) { if (empty($plan)) {
return ["node" => 0, "cpu" => 0]; return ["node" => 0, "cpu" => 0];
} }
/* Split CPUs per node */
$even = $odd = [];
foreach ($nodes as $n => $cpus) {
$even[$n] = array_values(array_filter($cpus, fn($c) => $c % 2 === 0));
$odd[$n] = array_values(array_filter($cpus, fn($c) => $c % 2 === 1));
}
$index = count($map); $index = count($map);
$slot = $plan[$index % count($plan)];
/* Count total EVEN cores */ $map[$serviceId] = $slot;
$totalEven = 0;
foreach ($even as $cpus) {
$totalEven += count($cpus);
}
/* Select phase */
if ($index < $totalEven) {
$phaseCpus = $even;
$phaseIndex = $index;
} else {
$phaseCpus = $odd;
$phaseIndex = $index - $totalEven;
}
/* Build list of nodes that actually have CPUs in this phase */
$activeNodes = [];
foreach ($phaseCpus as $n => $cpus) {
if (!empty($cpus)) {
$activeNodes[$n] = $cpus;
}
}
if (empty($activeNodes)) {
// Absolute fallback (should never happen)
return ["node" => 0, "cpu" => 0];
}
$nodeIds = array_keys($activeNodes);
$nodeCount = count($nodeIds);
/*
* Correct round-robin math
* First exhaust core index across all nodes,
* then move to next core.
*/
$nodeIndex = $phaseIndex % $nodeCount;
$coreIndex = intdiv($phaseIndex, $nodeCount);
$node = $nodeIds[$nodeIndex];
$cpuList = $activeNodes[$node];
// Safe wrap (never divide by zero now)
$cpu = $cpuList[$coreIndex % count($cpuList)];
$map[$serviceId] = [
"node" => $node,
"cpu" => $cpu
];
file_put_contents($coreFile, json_encode($map, JSON_PRETTY_PRINT)); file_put_contents($coreFile, json_encode($map, JSON_PRETTY_PRINT));
return $map[$serviceId];
return $slot;
} }
/* Free core */ /* ---------- HELPERS ---------- */
function freeCore(int $serviceId): void function freeCore(int $serviceId): void
{ {
global $coreFile; global $coreFile;
@ -113,7 +113,6 @@ function freeCore(int $serviceId): void
} }
} }
/* Get assigned core */
function getServiceCore(int $serviceId): ?array function getServiceCore(int $serviceId): ?array
{ {
global $coreFile; global $coreFile;