Browse Source

Added advanced parallel process calculation (#14437)

JPVenson 4 days ago
parent
commit
7ba77804c4

+ 24 - 5
MediaBrowser.Controller/LibraryTaskScheduler/LimitedConcurrencyLibraryScheduler.cs

@@ -96,14 +96,33 @@ public sealed class LimitedConcurrencyLibraryScheduler : ILimitedConcurrencyLibr
         }
     }
 
+    private bool ShouldForceSequentialOperation()
+    {
+        // if the user either set the setting to 1 or it's unset and we have fewer than 4 cores it's better to run sequentially.
+        var fanoutSetting = _serverConfigurationManager.Configuration.LibraryScanFanoutConcurrency;
+        return fanoutSetting == 1 || (fanoutSetting <= 0 && Environment.ProcessorCount <= 3);
+    }
+
+    private int CalculateScanConcurrencyLimit()
+    {
+        // when this is invoked, we already checked ShouldForceSequentialOperation for the sequential check.
+        var fanoutConcurrency = _serverConfigurationManager.Configuration.LibraryScanFanoutConcurrency;
+        if (fanoutConcurrency <= 0)
+        {
+            // in case the user did not set a limit manually, we can assume he has 3 or more cores as already checked by ShouldForceSequentialOperation.
+            return Environment.ProcessorCount - 3;
+        }
+
+        return fanoutConcurrency;
+    }
+
     private void Worker()
     {
         lock (_taskLock)
         {
-            var fanoutConcurrency = _serverConfigurationManager.Configuration.LibraryScanFanoutConcurrency;
-            var parallelism = (fanoutConcurrency > 0 ? fanoutConcurrency : Environment.ProcessorCount) - _taskRunners.Count;
-            _logger.LogDebug("Spawn {NumberRunners} new runners.", parallelism);
-            for (int i = 0; i < parallelism; i++)
+            var operationFanout = Math.Max(0, CalculateScanConcurrencyLimit() - _taskRunners.Count);
+            _logger.LogDebug("Spawn {NumberRunners} new runners.", operationFanout);
+            for (int i = 0; i < operationFanout; i++)
             {
                 var stopToken = new CancellationTokenSource();
                 var combinedSource = CancellationTokenSource.CreateLinkedTokenSource(stopToken.Token, _hostApplicationLifetime.ApplicationStopping);
@@ -223,7 +242,7 @@ public sealed class LimitedConcurrencyLibraryScheduler : ILimitedConcurrencyLibr
             };
         }).ToArray();
 
-        if (_serverConfigurationManager.Configuration.LibraryScanFanoutConcurrency == 1)
+        if (ShouldForceSequentialOperation())
         {
             _logger.LogDebug("Process sequentially.");
             try