From 7ba77804c414d012df311f9a5d644078dfa4a94a Mon Sep 17 00:00:00 2001 From: JPVenson Date: Sat, 12 Jul 2025 08:27:13 +0300 Subject: [PATCH] Added advanced parallel process calculation (#14437) --- .../LimitedConcurrencyLibraryScheduler.cs | 29 +++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/MediaBrowser.Controller/LibraryTaskScheduler/LimitedConcurrencyLibraryScheduler.cs b/MediaBrowser.Controller/LibraryTaskScheduler/LimitedConcurrencyLibraryScheduler.cs index f1428d6b97..0de5f198d7 100644 --- a/MediaBrowser.Controller/LibraryTaskScheduler/LimitedConcurrencyLibraryScheduler.cs +++ b/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