/// <summary> /// Determines the maximum number of actions to execute in parallel, taking into account the resources available on this machine. /// </summary> /// <returns>Max number of actions to execute in parallel</returns> public virtual int GetMaxActionsToExecuteInParallel() { // Get the number of logical processors int NumLogicalCores = Utils.GetLogicalProcessorCount(); // Use WMI to figure out physical cores, excluding hyper threading. int NumPhysicalCores = Utils.GetPhysicalProcessorCount(); if (NumPhysicalCores == -1) { NumPhysicalCores = NumLogicalCores; } // The number of actions to execute in parallel is trying to keep the CPU busy enough in presence of I/O stalls. int MaxActionsToExecuteInParallel = 0; if (NumPhysicalCores < NumLogicalCores && ProcessorCountMultiplier != 1.0) { // The CPU has more logical cores than physical ones, aka uses hyper-threading. // Use multiplier if provided MaxActionsToExecuteInParallel = (int)(NumPhysicalCores * ProcessorCountMultiplier); } else if (NumPhysicalCores < NumLogicalCores && NumPhysicalCores > 4) { // The CPU has more logical cores than physical ones, aka uses hyper-threading. // Use average of logical and physical if we have "lots of cores" MaxActionsToExecuteInParallel = Math.Max((int)(NumPhysicalCores + NumLogicalCores) / 2, NumLogicalCores - 4); } // No hyper-threading. Only kicking off a task per CPU to keep machine responsive. else { MaxActionsToExecuteInParallel = NumPhysicalCores; } #if !NET_CORE if (Utils.IsRunningOnMono) { long PhysicalRAMAvailableMB = (new PerformanceCounter("Mono Memory", "Total Physical Memory").RawValue) / (1024 * 1024); // heuristic: give each action at least 1.5GB of RAM (some clang instances will need more) if the total RAM is low, or 1GB on 16+GB machines long MinMemoryPerActionMB = (PhysicalRAMAvailableMB < 16384) ? 3 * 1024 / 2 : 1024; int MaxActionsAffordedByMemory = (int)(Math.Max(1, (PhysicalRAMAvailableMB) / MinMemoryPerActionMB)); MaxActionsToExecuteInParallel = Math.Min(MaxActionsToExecuteInParallel, MaxActionsAffordedByMemory); } #endif MaxActionsToExecuteInParallel = Math.Max(1, Math.Min(MaxActionsToExecuteInParallel, MaxProcessorCount)); return(MaxActionsToExecuteInParallel); }