Skip to content

Instantly share code, notes, and snippets.

@seif
Last active February 24, 2021 15:15
Show Gist options
  • Save seif/664bf7c2c7f860df5a2652611dd59cce to your computer and use it in GitHub Desktop.
Save seif/664bf7c2c7f860df5a2652611dd59cce to your computer and use it in GitHub Desktop.
Get real number of cpus on machine, ignoring any quotas/limits.
namespace Utilities
{
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
public static class Machine
{
private const int MaximumNumberOfCpus = 128;
private static int? _processorCount;
/// <summary>
/// Returns the actual processor counts on the machine.
/// This was needed in docker because Environment.ProcessorCount was returning the cpu value taking into account
/// CPU limits set.
/// In order to check how many cpus actually exist on the machine, we loop from 0 to 127, asking libc to give us
/// the affinity of the current process to the cpuIndex. If the operation succeeds and we get a result, cpu exists
/// if it returns -1 then the operatin failed and cpu doesn't exist.
/// </summary>
public static int ProcessorCount
{
get
{
if (_processorCount.HasValue)
{
return _processorCount.Value;
}
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
_processorCount = Environment.ProcessorCount;
return Environment.ProcessorCount;
}
else
{
ulong count = 0;
ulong result = 0;
while (LibC.sched_getaffinity(Process.GetCurrentProcess().Id, (IntPtr)count, ref result) != 0 && count < MaximumNumberOfCpus)
{
count++;
}
_processorCount = Math.Max((int)count, 1);
}
return _processorCount.Value;
}
}
}
internal static class LibC
{
private const string DllName = "libc";
/// <summary>
/// Calls libc sched_getaffinity https://linux.die.net/man/2/sched_getaffinity
/// </summary>
/// <param name="pid">The pid to get the affinity for</param>
/// <param name="cpuSetSize">Value passed is the index of the cpu</param>
/// <param name="affinityResult">The affinity of the current process to the cpu specified</param>
/// <returns>-1 on error, 0 on success</returns>
[DllImport(DllName)]
internal static extern int sched_getaffinity(int pid, IntPtr cpuSetSize, ref ulong affinityResult);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment