NUMA-Aware Zone Placement in Edera Explained
Use Cases
Resources
Company
Contact
Products<br>For ContainersFor GPUs<br>Use Cases<br>Multi-Tenant IsolationUntrusted Code ExecutionAI Agent Sandboxing<br>Resources<br>The VineEventsDocs<br>WHO WE ARE<br>Why EderaSocial LovePress & Events<br>BEHIND THE SCENES<br>CareersLegal<br>FOLLOW<br>LinkedInYouTubeBluesky<br>Support<br>Contact EderaEdera GitHub
NUMA Part 2: NUMA-Aware Zone Placement — How Edera Decides<br>July 2, 2026 - Steven Noonan
Part 1 of this series ended with a question the operator actually has to answer: "where should this zone live?" Leave it unanswered and the answer defaults to "wherever the scheduler last put it" - the unpredictable case from the previous post, where the same workload runs at 80% of its potential one day and 100% the next. That swing is only the visible part; underneath it is a hardware bill - remote-memory latency and cross-node coherence on accesses the workload assumed were local - that a misplaced zone keeps paying, request after request, for as long as it runs.<br>Edera answers that question automatically. A zone goes onto specific Non-Uniform Memory Access (NUMA) nodes the moment it boots, with a vNUMA topology that matches its physical placement, and its vCPUs are pinned to the pCPUs of those nodes. The operator does not configure any of this in the common case. For the cases where the defaults are wrong, there are explicit knobs.<br>Why NUMA-aware zones must be PVH<br>Before any of the rest of this matters, one requirement governs all of it: a zone can only be NUMA-aware if it runs as PVH, not PV. This is not a tuning detail or a soft recommendation. It is the line between a guest that can see its topology and one that is blind to it, and no amount of configuration moves that line.<br>The reason is mechanical. A guest learns its NUMA layout from ACPI tables and from the CPU identifiers it reads at boot - the same channels real hardware uses. A PV guest has neither: there are no ACPI tables in the PV environment (it does not boot through firmware), and its CPU identifiers are synthetic - a flat enumeration with no topology in them. The information has nowhere to enter the guest. Part 3 gets into why that is structural - a consequence of PV having no firmware - rather than merely unimplemented.<br>PV zones still run perfectly well on a multi-NUMA host - they simply see a single flat node. That makes PV a safe choice for a zone small enough to fit inside one host NUMA node, where "one flat node" and the truth are the same thing. Ask for a PV zone larger than a single node, though, and the host will still place it - spreading it across as many physical nodes as it takes - while the guest goes on believing it has one uniform pool of memory. It cannot make a single deliberate decision about locality, because it has no idea there is any locality to reason about. That is precisely the unpredictable performance case from part 1.<br>So the requirement comes down to a simple test. A zone that fits in one NUMA node can be PV and lose nothing. A zone bigger than that, or one you want to make deliberate use of the hardware it lands on, has to be PVH. Everything from here on assumes PVH.<br>What changes when a zone is NUMA-aware<br>A NUMA-aware zone is not magic. It is a virtual machine that has been given an accurate description of the topology it is running on, in the same formats that real hardware uses to describe itself to a real operating system. So what does that description actually consist of? On x86, three pieces - and a guest needs all three together. Hand it the memory tables but a flat CPU map and it will place its threads as if every core were interchangeable, undoing the locality the other two pieces just described.<br>System Resource Affinity Table (SRAT)<br>The SRAT is an ACPI table that says "these CPUs and these memory ranges belong to NUMA node N". It is how the OS in the guest learns it has a NUMA topology at all. On the kind of host this series will keep coming back to - a dual-socket AMD EPYC box in 4-nodes-per-socket mode, eight NUMA nodes total, sixteen CPUs per node, sixteen GiB per node - an abbreviated SRAT looks something like:<br>Proximity Domain 0 -> CPUs 0-15 Memory: 16 GiB<br>Proximity Domain 1 -> CPUs 16-31 Memory: 16 GiB<br>Proximity Domain 2 -> CPUs 32-47 Memory: 16 GiB<br>...<br>Proximity Domain 7 -> CPUs 112-127 Memory: 16 GiB<br>("Proximity Domain" in ACPI parlance is the same thing as a NUMA node; the table predates the term "NUMA node" being standard vocabulary.)<br>System Locality Information Table (SLIT)<br>The SLIT is an ACPI distance matrix: same nodes on both axes, with the relative cost of reaching column M from row N at each intersection. The OS uses it to decide how strongly to prefer local memory and how to rank fallback nodes when local memory runs out. The SLIT for the same 8-node host looks like this:<br>Node: 0 1 2 3 4 5 6 7<br>0 10 12 12 12 32 32 32 32<br>1 12 10 12 12 32 32 32 32<br>2 12 12 10 12 32 32 32 32<br>3 12 12 12 10 32 32 32 32<br>4 32 32 32 32 10 12 12 12<br>5 32 32 32 32 12 10...