Skip to content

Commit

Permalink
Reduce bottlenecks scan code (#9863)
Browse files Browse the repository at this point in the history
  • Loading branch information
Bond-009 committed Jun 22, 2023
1 parent d14b1a1 commit 3982b0e
Show file tree
Hide file tree
Showing 13 changed files with 64 additions and 219 deletions.
20 changes: 4 additions & 16 deletions Jellyfin.Api/Controllers/LibraryController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -969,12 +969,8 @@ private bool IsMetadataFetcherEnabledByDefault(string name, string type, bool is
|| string.Equals(name, "MusicBrainz", StringComparison.OrdinalIgnoreCase);
}

var metadataOptions = _serverConfigurationManager.Configuration.MetadataOptions
.Where(i => string.Equals(i.ItemType, type, StringComparison.OrdinalIgnoreCase))
.ToArray();

return metadataOptions.Length == 0
|| metadataOptions.Any(i => !i.DisabledMetadataFetchers.Contains(name, StringComparison.OrdinalIgnoreCase));
var metadataOptions = _serverConfigurationManager.GetMetadataOptionsForType(type);
return metadataOptions is null || !metadataOptions.DisabledMetadataFetchers.Contains(name, StringComparison.OrdinalIgnoreCase);
}

private bool IsImageFetcherEnabledByDefault(string name, string type, bool isNewLibrary)
Expand All @@ -995,15 +991,7 @@ private bool IsImageFetcherEnabledByDefault(string name, string type, bool isNew
|| string.Equals(name, "Image Extractor", StringComparison.OrdinalIgnoreCase);
}

var metadataOptions = _serverConfigurationManager.Configuration.MetadataOptions
.Where(i => string.Equals(i.ItemType, type, StringComparison.OrdinalIgnoreCase))
.ToArray();

if (metadataOptions.Length == 0)
{
return true;
}

return metadataOptions.Any(i => !i.DisabledImageFetchers.Contains(name, StringComparison.OrdinalIgnoreCase));
var metadataOptions = _serverConfigurationManager.GetMetadataOptionsForType(type);
return metadataOptions is null || !metadataOptions.DisabledImageFetchers.Contains(name, StringComparison.OrdinalIgnoreCase);
}
}
65 changes: 7 additions & 58 deletions MediaBrowser.Controller/BaseItemManager/BaseItemManager.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Threading;
using Jellyfin.Extensions;
using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Configuration;

namespace MediaBrowser.Controller.BaseItemManager
Expand All @@ -15,25 +14,15 @@ public class BaseItemManager : IBaseItemManager
{
private readonly IServerConfigurationManager _serverConfigurationManager;

private int _metadataRefreshConcurrency;

/// <summary>
/// Initializes a new instance of the <see cref="BaseItemManager"/> class.
/// </summary>
/// <param name="serverConfigurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</param>
public BaseItemManager(IServerConfigurationManager serverConfigurationManager)
{
_serverConfigurationManager = serverConfigurationManager;

_metadataRefreshConcurrency = GetMetadataRefreshConcurrency();
SetupMetadataThrottler();

_serverConfigurationManager.ConfigurationUpdated += OnConfigurationUpdated;
}

/// <inheritdoc />
public SemaphoreSlim MetadataRefreshThrottler { get; private set; }

/// <inheritdoc />
public bool IsMetadataFetcherEnabled(BaseItem baseItem, TypeOptions? libraryTypeOptions, string name)
{
Expand All @@ -51,12 +40,11 @@ public bool IsMetadataFetcherEnabled(BaseItem baseItem, TypeOptions? libraryType

if (libraryTypeOptions is not null)
{
return libraryTypeOptions.MetadataFetchers.Contains(name.AsSpan(), StringComparison.OrdinalIgnoreCase);
return libraryTypeOptions.MetadataFetchers.Contains(name, StringComparison.OrdinalIgnoreCase);
}

var itemConfig = _serverConfigurationManager.Configuration.MetadataOptions.FirstOrDefault(i => string.Equals(i.ItemType, baseItem.GetType().Name, StringComparison.OrdinalIgnoreCase));

return itemConfig is null || !itemConfig.DisabledMetadataFetchers.Contains(name.AsSpan(), StringComparison.OrdinalIgnoreCase);
var itemConfig = _serverConfigurationManager.GetMetadataOptionsForType(baseItem.GetType().Name);
return itemConfig is null || !itemConfig.DisabledMetadataFetchers.Contains(name, StringComparison.OrdinalIgnoreCase);
}

/// <inheritdoc />
Expand All @@ -76,50 +64,11 @@ public bool IsImageFetcherEnabled(BaseItem baseItem, TypeOptions? libraryTypeOpt

if (libraryTypeOptions is not null)
{
return libraryTypeOptions.ImageFetchers.Contains(name.AsSpan(), StringComparison.OrdinalIgnoreCase);
}

var itemConfig = _serverConfigurationManager.Configuration.MetadataOptions.FirstOrDefault(i => string.Equals(i.ItemType, baseItem.GetType().Name, StringComparison.OrdinalIgnoreCase));

return itemConfig is null || !itemConfig.DisabledImageFetchers.Contains(name.AsSpan(), StringComparison.OrdinalIgnoreCase);
}

/// <summary>
/// Called when the configuration is updated.
/// It will refresh the metadata throttler if the relevant config changed.
/// </summary>
private void OnConfigurationUpdated(object? sender, EventArgs e)
{
int newMetadataRefreshConcurrency = GetMetadataRefreshConcurrency();
if (_metadataRefreshConcurrency != newMetadataRefreshConcurrency)
{
_metadataRefreshConcurrency = newMetadataRefreshConcurrency;
SetupMetadataThrottler();
}
}

/// <summary>
/// Creates the metadata refresh throttler.
/// </summary>
[MemberNotNull(nameof(MetadataRefreshThrottler))]
private void SetupMetadataThrottler()
{
MetadataRefreshThrottler = new SemaphoreSlim(_metadataRefreshConcurrency);
}

/// <summary>
/// Returns the metadata refresh concurrency.
/// </summary>
private int GetMetadataRefreshConcurrency()
{
var concurrency = _serverConfigurationManager.Configuration.LibraryMetadataRefreshConcurrency;

if (concurrency <= 0)
{
concurrency = Environment.ProcessorCount;
return libraryTypeOptions.ImageFetchers.Contains(name, StringComparison.OrdinalIgnoreCase);
}

return concurrency;
var itemConfig = _serverConfigurationManager.GetMetadataOptionsForType(baseItem.GetType().Name);
return itemConfig is null || !itemConfig.DisabledImageFetchers.Contains(name, StringComparison.OrdinalIgnoreCase);
}
}
}
5 changes: 0 additions & 5 deletions MediaBrowser.Controller/BaseItemManager/IBaseItemManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,6 @@ namespace MediaBrowser.Controller.BaseItemManager
/// </summary>
public interface IBaseItemManager
{
/// <summary>
/// Gets the semaphore used to limit the amount of concurrent metadata refreshes.
/// </summary>
SemaphoreSlim MetadataRefreshThrottler { get; }

/// <summary>
/// Is metadata fetcher enabled.
/// </summary>
Expand Down
2 changes: 1 addition & 1 deletion MediaBrowser.Controller/Entities/Audio/MusicArtist.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public override IEnumerable<BaseItem> Children
{
if (IsAccessedByName)
{
return new List<BaseItem>();
return Enumerable.Empty<BaseItem>();
}

return base.Children;
Expand Down
33 changes: 8 additions & 25 deletions MediaBrowser.Controller/Entities/BaseItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1244,14 +1244,6 @@ public Task RefreshMetadata(CancellationToken cancellationToken)
return RefreshMetadata(new MetadataRefreshOptions(new DirectoryService(FileSystem)), cancellationToken);
}

protected virtual void TriggerOnRefreshStart()
{
}

protected virtual void TriggerOnRefreshComplete()
{
}

/// <summary>
/// Overrides the base implementation to refresh metadata for local trailers.
/// </summary>
Expand All @@ -1260,8 +1252,6 @@ protected virtual void TriggerOnRefreshComplete()
/// <returns>true if a provider reports we changed.</returns>
public async Task<ItemUpdateType> RefreshMetadata(MetadataRefreshOptions options, CancellationToken cancellationToken)
{
TriggerOnRefreshStart();

var requiresSave = false;

if (SupportsOwnedItems)
Expand All @@ -1281,21 +1271,14 @@ public async Task<ItemUpdateType> RefreshMetadata(MetadataRefreshOptions options
}
}

try
{
var refreshOptions = requiresSave
? new MetadataRefreshOptions(options)
{
ForceSave = true
}
: options;
var refreshOptions = requiresSave
? new MetadataRefreshOptions(options)
{
ForceSave = true
}
: options;

return await ProviderManager.RefreshSingleItem(this, refreshOptions, cancellationToken).ConfigureAwait(false);
}
finally
{
TriggerOnRefreshComplete();
}
return await ProviderManager.RefreshSingleItem(this, refreshOptions, cancellationToken).ConfigureAwait(false);
}

protected bool IsVisibleStandaloneInternal(User user, bool checkFolders)
Expand Down Expand Up @@ -1367,7 +1350,7 @@ protected virtual FileSystemMetadata[] GetFileSystemChildren(IDirectoryService d
private async Task<bool> RefreshExtras(BaseItem item, MetadataRefreshOptions options, IReadOnlyList<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken)
{
var extras = LibraryManager.FindExtras(item, fileSystemChildren, options.DirectoryService).ToArray();
var newExtraIds = extras.Select(i => i.Id).ToArray();
var newExtraIds = Array.ConvertAll(extras, x => x.Id);
var extrasChanged = !item.ExtraIds.SequenceEqual(newExtraIds);

if (!extrasChanged && !options.ReplaceAllMetadata && options.MetadataRefreshMode != MetadataRefreshMode.FullRefresh)
Expand Down
38 changes: 9 additions & 29 deletions MediaBrowser.Controller/Entities/Folder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -301,14 +301,6 @@ public Task ValidateChildren(IProgress<double> progress, MetadataRefreshOptions
return dictionary;
}

protected override void TriggerOnRefreshStart()
{
}

protected override void TriggerOnRefreshComplete()
{
}

/// <summary>
/// Validates the children internal.
/// </summary>
Expand Down Expand Up @@ -510,37 +502,25 @@ private Task RefreshMetadataRecursive(IList<BaseItem> children, MetadataRefreshO

private async Task RefreshAllMetadataForContainer(IMetadataContainer container, MetadataRefreshOptions refreshOptions, IProgress<double> progress, CancellationToken cancellationToken)
{
// limit the amount of concurrent metadata refreshes
await ProviderManager.RunMetadataRefresh(
async () =>
{
var series = container as Series;
if (series is not null)
{
await series.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false);
}
if (container is Series series)
{
await series.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false);
}

await container.RefreshAllMetadata(refreshOptions, progress, cancellationToken).ConfigureAwait(false);
},
cancellationToken).ConfigureAwait(false);
await container.RefreshAllMetadata(refreshOptions, progress, cancellationToken).ConfigureAwait(false);
}

private async Task RefreshChildMetadata(BaseItem child, MetadataRefreshOptions refreshOptions, bool recursive, IProgress<double> progress, CancellationToken cancellationToken)
{
var container = child as IMetadataContainer;

if (container is not null)
if (child is IMetadataContainer container)
{
await RefreshAllMetadataForContainer(container, refreshOptions, progress, cancellationToken).ConfigureAwait(false);
}
else
{
if (refreshOptions.RefreshItem(child))
{
// limit the amount of concurrent metadata refreshes
await ProviderManager.RunMetadataRefresh(
async () => await child.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false),
cancellationToken).ConfigureAwait(false);
await child.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false);
}

if (recursive && child is Folder folder)
Expand Down Expand Up @@ -586,7 +566,7 @@ void UpdateProgress()
}

var fanoutConcurrency = ConfigurationManager.Configuration.LibraryScanFanoutConcurrency;
var parallelism = fanoutConcurrency == 0 ? Environment.ProcessorCount : fanoutConcurrency;
var parallelism = fanoutConcurrency > 0 ? fanoutConcurrency : 2 * Environment.ProcessorCount;

var actionBlock = new ActionBlock<int>(
async i =>
Expand Down Expand Up @@ -618,7 +598,7 @@ void UpdateProgress()

for (var i = 0; i < childrenCount; i++)
{
actionBlock.Post(i);
await actionBlock.SendAsync(i).ConfigureAwait(false);
}

actionBlock.Complete();
Expand Down
17 changes: 12 additions & 5 deletions MediaBrowser.Controller/Library/MetadataConfigurationExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
#nullable disable

#pragma warning disable CS1591

using System;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Model.Configuration;

namespace MediaBrowser.Controller.Library
{
public static class MetadataConfigurationExtensions
{
public static MetadataConfiguration GetMetadataConfiguration(this IConfigurationManager config)
{
return config.GetConfiguration<MetadataConfiguration>("metadata");
}
=> config.GetConfiguration<MetadataConfiguration>("metadata");

/// <summary>
/// Gets the <see cref="MetadataOptions" /> for the specified type.
/// </summary>
/// <param name="config">The <see cref="IServerConfigurationManager"/>.</param>
/// <param name="type">The type to get the <see cref="MetadataOptions" /> for.</param>
/// <returns>The <see cref="MetadataOptions" /> for the specified type or <c>null</c>.</returns>
public static MetadataOptions? GetMetadataOptionsForType(this IServerConfigurationManager config, string type)
=> Array.Find(config.Configuration.MetadataOptions, i => string.Equals(i.ItemType, type, StringComparison.OrdinalIgnoreCase));
}
}
17 changes: 0 additions & 17 deletions MediaBrowser.Controller/Providers/IProviderManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,6 @@ public interface IProviderManager
/// <returns>Task.</returns>
Task<ItemUpdateType> RefreshSingleItem(BaseItem item, MetadataRefreshOptions options, CancellationToken cancellationToken);

/// <summary>
/// Runs multiple metadata refreshes concurrently.
/// </summary>
/// <param name="action">The action to run.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>A <see cref="Task"/> representing the result of the asynchronous operation.</returns>
Task RunMetadataRefresh(Func<Task> action, CancellationToken cancellationToken);

/// <summary>
/// Saves the image.
/// </summary>
Expand Down Expand Up @@ -207,15 +199,6 @@ IEnumerable<IMetadataProvider<T>> GetMetadataProviders<T>(BaseItem item, Library
where TItemType : BaseItem, new()
where TLookupType : ItemLookupInfo;

/// <summary>
/// Gets the search image.
/// </summary>
/// <param name="providerName">Name of the provider.</param>
/// <param name="url">The URL.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{HttpResponseInfo}.</returns>
Task<HttpResponseMessage> GetSearchImage(string providerName, string url, CancellationToken cancellationToken);

HashSet<Guid> GetRefreshQueue();

void OnRefreshStart(BaseItem item);
Expand Down
5 changes: 4 additions & 1 deletion MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public class MediaEncoder : IMediaEncoder, IDisposable
private readonly IServerConfigurationManager _serverConfig;
private readonly string _startupOptionFFmpegPath;

private readonly SemaphoreSlim _thumbnailResourcePool = new SemaphoreSlim(2, 2);
private readonly SemaphoreSlim _thumbnailResourcePool;

private readonly object _runningProcessesLock = new object();
private readonly List<ProcessWrapper> _runningProcesses = new List<ProcessWrapper>();
Expand Down Expand Up @@ -113,6 +113,9 @@ public class MediaEncoder : IMediaEncoder, IDisposable

_jsonSerializerOptions = new JsonSerializerOptions(JsonDefaults.Options);
_jsonSerializerOptions.Converters.Add(new JsonBoolStringConverter());

var semaphoreCount = 2 * Environment.ProcessorCount;
_thumbnailResourcePool = new SemaphoreSlim(semaphoreCount, semaphoreCount);
}

/// <inheritdoc />
Expand Down
Loading

0 comments on commit 3982b0e

Please sign in to comment.