rewrite of swiss, swiss will not be public but l4 specific

This commit is contained in:
Youmu Liu
2026-10-08 18:15:05 +08:00
parent 1845a00390
commit 2e7c3040f4
18 changed files with 367 additions and 391 deletions
@@ -16,22 +16,21 @@ namespace Nitload.Common.HighPerformance.ProcessorAbstraction
public readonly struct LogicalCore
{
public readonly uint GlobalCpuId;
public readonly uint NumaGroupId;
/// <summary>
/// Stays 0 on linux.
/// </summary>
public readonly uint ProcessorGroupId;
public readonly uint SocketId;
public readonly uint CpuIndex;
public readonly uint NumaNodeId;
internal LogicalCore(
uint globalCpuId,
uint numaGroupId,
uint processorGroupId,
uint socketId,
uint cpuIndex,
uint numaNodeId
)
{
GlobalCpuId = globalCpuId;
NumaGroupId = numaGroupId;
ProcessorGroupId = processorGroupId;
SocketId = socketId;
CpuIndex = cpuIndex;
NumaNodeId = numaNodeId;
}
@@ -33,7 +33,7 @@ namespace Nitload.Common.HighPerformance.ProcessorAbstraction
if (_numaNodes.Length == 0) {
throw new InvalidOperationException("Numa info has not been loaded.");
}
if ((numaId < 0) || (numaId >= _numaNodes.Length)) {
if ((numaId < 0) || !ContainsNode((uint)numaId)) {
throw new ArgumentOutOfRangeException(nameof(numaId), "Invalid NUMA node ID.");
}
return NumaAllocNative(size, numaId);
@@ -69,7 +69,7 @@ namespace Nitload.Common.HighPerformance.ProcessorAbstraction
if (_numaNodes.Length == 0) {
throw new InvalidOperationException("Numa info has not been loaded.");
}
if ((numaId < 0) || (numaId >= _numaNodes.Length)) {
if ((numaId < 0) || !ContainsNode((uint)numaId)) {
throw new ArgumentOutOfRangeException(nameof(numaId), "Invalid NUMA node ID.");
}
NumaFreeNative(address, size, numaId);
@@ -80,8 +80,10 @@ namespace Nitload.Common.HighPerformance.ProcessorAbstraction
[DefaultDllImportSearchPaths(DllImportSearchPath.AssemblyDirectory)]
public static partial int GetNumaEach(
uint numaId,
Span<ulong> CpuIndexInNuma,
Span<uint> globalCpuIdInNuma
Span<uint> processorGroupIds,
Span<uint> socketIds,
Span<uint> cpuIndices,
Span<uint> numaNodeIds
);
[LibraryImport(Native.LibName, EntryPoint = "nif_get_numa_overall")]
@@ -97,10 +99,10 @@ namespace Nitload.Common.HighPerformance.ProcessorAbstraction
if (_numaNodes.Length == 0) {
throw new InvalidOperationException("Numa info has not been loaded.");
}
L4[] buffers = new L4[NumaNodeCount];
for (int i = 0; i < NumaNodeCount; i++)
L4[] buffers = new L4[_numaNodes.Length];
for (int i = 0; i < _numaNodes.Length; i++)
{
L4 buffer = new L4(i);
L4 buffer = new L4((int)_numaNodes[i].NumaNodeId);
buffers[i] = buffer;
}
return buffers;
@@ -108,14 +110,29 @@ namespace Nitload.Common.HighPerformance.ProcessorAbstraction
internal static void Initialize()
{
Span<int> coreCountInNuma = stackalloc int[(Environment.ProcessorCount / 32) + 1];
int numaNodeCount = 0;
if (0 == GetNumaOverall(ref numaNodeCount, coreCountInNuma)) {
if (0 == GetNumaOverall(ref numaNodeCount, default)) {
throw new InvalidOperationException("Failed to get NUMA overall information.");
}
_numaNodes = new NumaNode[numaNodeCount];
for (uint i = 0; i < numaNodeCount; i++) {
_numaNodes[i] = InitNumaNode(i, coreCountInNuma[(int)i]);
int[] coreCountInNuma = new int[numaNodeCount];
if (0 == GetNumaOverall(ref numaNodeCount, coreCountInNuma)) {
throw new InvalidOperationException("Failed to get NUMA node processor counts.");
}
int activeNodeCount = 0;
for (int i = 0; i < coreCountInNuma.Length; i++) {
if (coreCountInNuma[i] > 0) {
activeNodeCount++;
}
}
NumaNodeCount = activeNodeCount;
_numaNodes = new NumaNode[activeNodeCount];
int nodeIndex = 0;
for (uint numaId = 0; numaId < numaNodeCount; numaId++) {
int coreCount = coreCountInNuma[(int)numaId];
if (coreCount == 0) {
continue;
}
_numaNodes[nodeIndex++] = InitNumaNode(numaId, coreCount);
}
}
@@ -123,8 +140,8 @@ namespace Nitload.Common.HighPerformance.ProcessorAbstraction
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
[DefaultDllImportSearchPaths(DllImportSearchPath.AssemblyDirectory)]
internal static partial void SetThreadAffinity(
int coreId,
int numaId
int cpuIndex,
int processorGroupId
);
[MethodImpl(MethodImplOptions.NoInlining)]
@@ -133,9 +150,24 @@ namespace Nitload.Common.HighPerformance.ProcessorAbstraction
int count
)
{
Span<uint> globalIndex = stackalloc uint[count];
_ = GetNumaEach(numaId, null, globalIndex);
return new(numaId, count, globalIndex);
Span<uint> processorGroupIds = stackalloc uint[count];
Span<uint> socketIds = stackalloc uint[count];
Span<uint> cpuIndices = stackalloc uint[count];
Span<uint> numaNodeIds = stackalloc uint[count];
if (0 == GetNumaEach(numaId, processorGroupIds, socketIds, cpuIndices, numaNodeIds)) {
throw new InvalidOperationException($"Failed to enumerate processors for NUMA node {numaId}.");
}
return new(numaId, count, processorGroupIds, socketIds, cpuIndices, numaNodeIds);
}
private static bool ContainsNode(uint numaId)
{
foreach (NumaNode node in _numaNodes) {
if (node.NumaNodeId == numaId) {
return true;
}
}
return false;
}
[LibraryImport(Native.LibName, EntryPoint = "nif_numa_alloc")]
@@ -22,16 +22,26 @@ namespace Nitload.Common.HighPerformance.ProcessorAbstraction
internal NumaNode(
uint numaId,
int count,
Span<uint> logicalCoreIds
Span<uint> processorGroupIds,
Span<uint> socketIds,
Span<uint> cpuIndices,
Span<uint> numaNodeIds
)
{
NumaNodeId = numaId;
_logicalCores = new LogicalCore[count];
for (int i = 0; i < count; i++) {
_logicalCores[i] = new LogicalCore((uint)i, numaId, logicalCoreIds[i]);
_logicalCores[i] = new LogicalCore(
processorGroupIds[i],
socketIds[i],
cpuIndices[i],
numaNodeIds[i]);
}
}
public uint NumaNodeId { get; }
public int LogicalCoreCount => _logicalCores.Length;
public ReadOnlySpan<LogicalCore> LogicalCores => _logicalCores;